Category Archives: General

El ayuntamiento de Ciudad Real inventa denuncias

3
Filed under General
Si no lo digo reviento. Y es que todo sucedió un fatídico 29 de Octubre de 2009, a eso de las 9:00AM, en la glorieta que hay en la esquina de la Ronda Granada con la el Paseo Carlos Eraña, en Ciudad Real capital.

A continuación de dicha glorieta hay un bonito paso de peatones sin semáforo y al lado un Insituto, que a la hora de los hechos estaba, como es de suponer, rebosante de hormonas entrando en él….

Pues a esto que voy yo, como todos los días a TRABAJAR (es lo que tenemos las personas honradas, que como no estafamos, tenemos que trabajar nos guste o no) y me veo que dirigiendo el tráfico había un policía local. Ciertamente he de decir, que cuando lo ví no supe exactamente que estaba indicando, así que como había bastante tráfico (esa glorieta y la de la Estación de Autobuses dan verdadero miedo a ciertas horas de la mañana) pues me dije “Bueno, lo que haga el de delante, como vamos en primera….”. Y así fue, yo en primera, paso la glorieta, como el que venía delante de mi, que cruza el paso de peatones mientras la gente está esperando en la acera. Yo, incauto de mi, decido pasar también (no sé, puede que tuviera algo que ver el hecho de que no me dijeron alto ni el policía cambió de actitud…) y mientras estoy pasando, el buen hombre me da la señal de alto.

Frenazo que te crió (en la autoescuela parece ser que no enseñan que un policía puede decirte “alto” mientras ya estás cruzando). El caso es que paro, pero en la segunda mitad del paso de peatones, ya saliendo. Se me acerca el buen hombre y me dice con semblante serio:

Poli: -“¿Qué pasa con usted?”
Yo: -“Ehmmmmm, lo siento, ya estaba cruzando cuando dió la señal de STOP, no me ha dado tiempo a parar antes…”
Poli: -“Bueno, no se preocupe, continúe, pero tenga mas cuidado la próxima vez…”

Se vé que en la jerga de los hombres encargados de velar por el bien “No se preocupe” significa 4 puntos, Retirada temporal del permiso de conducción y 200 euros por las molestias.

Si señores si, eso fue lo que me llegó en una bonita notificación el día 28 de Diciembre de 2009 (y no, no era broma muy a mi pesar). ¿El motivo? “No obedecer las órdenes o señales de los agentes de la autoridad, sin peligro para otros”. Pues si. El buen hombre dice que no le obedecí (lo que da a entender que no paré y que me fui). Claro, como “no pasaba nada” y no me dió denuncia, yo ahora no puedo demostrar que esa denuncia es totalmente falsa. ¡¡Qué bien!!

El caso es que un amigo que conoce el funcionamiento de la policía local bastante bien (creo recordar que fue él quien me lo dijo, pero puede que me equivoque) me dijo: “Recurre, como ésta gente solo quiere tu dinero lo mas probable es que te perdonen la retirada. Te tienen que poner la denuncia completa para que no se note que van a lo que van….”.

Así lo hice, recurrí, y hoy al llegar al pueblo me encuentro una bonita notificación (siempre son buenas noticias, SIEMPRE) diciéndome que pague los 200 euros que me piden y me deje de gilipolleces (pero edulcorado con jerga judicial, que aquí te llaman Gilipollas con clase y estilo…). Eso si, ME HAN PERDONADO EL CARNET DE CONDUCIR. Ohhhh, no puedo mas que llorar ante tal muestra de compasión y benevolencia…

Pues nada, ésto es lo que me ha pasado. Tenía que contarlo, ya que siento una sensación de indefensión y de impotencia que muy pocas veces antes había sentido. Si señor, ahora siento seguridad cada vez que veo un coche de los locales por Ciudad Real, o cada vez que voy andando por el centro una mañana y me los encuentro paseando el tipito por la Plaza Mayor y aledaños a ver que se puede rascar…

He de decir, sin embargo, que de los 10 años que llevo viviendo en Ciudad Real, hasta hace algo menos de un año no sabía ni que teníamos policía local. Bueno, si que lo sabía, evidentemente, pero no porque los viese paseando o patrullando. Y es que la crisis está haciendo estragos, ya lo dicen en TeleMadrid…

Pues nada, un hurra por nuestra Alcaldesa, que ha encontrado la forma de solucionar los problemas económicos del ayuntamiento de tan insigne ciudad y otro hurra por el Agente 200-098, seguro que se llevó una palmadita en la espalda y todo…

Yo mientras tanto, como persona honrada que soy, seguiré durmiendo una media de cuatro horas al día para llegar a tiempo al trabajo y a mis estudios, que para que nos puedan robar con tanta impunidad, antes tenemos que tener algo…

GCC y el padding

0
Filed under Embedded, GCC, General, Programación
Tagged as , , ,

Introducción

Hace poco, en el trabajo, me encontraba realizando la implementación del protocolo descrito en la RFC 908 para usarla en un pequeño microcontrolador de Atmel.

Una vez implementado y compilado todo, me dispuse a realizar las correspondientes pruebas y vi que en ciertas funciones sucedían cosas muy extrañas. En concreto, tenía definidas varias estructuras en las que se almacenaba toda la información de estado y control del protocolo y descubrí que al intentar recorrer todos sus miembros con un puntero a char las cosas no cuadraban. Leía valores que se suponía que no estaban ahí o al calcular el tamaño de los mensajes basándome en el tamaño de las estructuras (calculadas usando sizeof) estos no eran los que tenían que ser….

¿Qué estaba sucediendo?

El problema: Padding

Pues si. Enseguida imaginé cual podría ser el problema: el Padding. La verdad es que es un error un poco de novatos, pero yo caí. Generalmente los programadores en lenguajes como C raramente suelen tener en cuenta el tema del padding a diseñar sus programas, puesto que suponen que el compilador se encargará de optimizar nuestro código y además, rara vez se trabaja a un nivel tan bajo como para que ésto sea un problema.

La cosa cambia si estás diseñando código para correr en un dispositivo empotrado con poca memoria o tienes que hacer manipulaciones a muy bajo nivel sobre las estructuras. En mi caso, se daban las dos situaciones, así que me puse a investigar un poco y ésto fue lo que aprendí.

¿Qué es exactamente el padding? Bueno, empecemos por el principio:

El Alineamiento

¿Y ésto qué es?. Bueno, dependiendo del tipo de máquina que estemos utilizando y del tipo de dato con el que estemos trabajando, el rango de direcciones en las que se puede almacenar dicho dato debe cumplir una u otra característica. Me explico: supongamos que estamos trabajando en una máquina de 32 bits. En éste caso, tendremos una máquina con una alineación de memoria de 4 bytes. Es decir, cualquier lectura de memoria se hace de cuatro en cuatro bytes y todas las posibles direcciones de memoria que se leen serán múltiplo de 4. Por tanto, una lectura, supongamos en la dirección 0x00abcd0034 sería correcta, mientras que si intentásemos leer de la dirección 0x00abcd0031 no podríamos, pues esa dirección no está alineada a 4 bytes (no es múltiplo de 4). Si queremos leer ese byte en concreto, deberemos leer la dirección 0x00abcd0030 y después acceder a los bits <8:15>
Hay que hacer una pequeña aclaración y comentar que ésto es para el caso de que nuestra máquina sea de 32 bits pero use una memoria de 8 bits. También podemos tener máquinas con un bus de memoria de igual longitud que los datos que utiliza, en cuyo caso, el alineamiento de las posiciones de memoria sería 1, es decir, se puede leer y escribir en cualquier dirección, pero se leerán 32 bits (o los que tenga el ancho del bus) de cada vez. Para lo que voy a explicar, me parece mas conveniente el modelo de máquina de 32 bits con un bus de 8, aunque esto es aplicable a cualquier tipo de arquitectura.

Si en la máquina de la que estamos hablando queremos guardar un char, dicha variable la podremos guardar, como podemos imaginar, en cualquier dirección (un char, como todos sabemos, ocupa 8 bits). Decimos que el alineamiento de éste tipo de variables es de un byte. Ésto sucede porque, en nuestra máquina de 32 bits, para leer un char, leeremos 32 bits (4 bytes) de una vez, y entre esos 4 bytes, estará el que buscamos.
La cosa cambia si ahora en lugar de querer almacenar un simple char queremos guardar un short (típicamente 16 bits). En éste caso solo podremos almacenarlo en direcciones múltiplo de 2. ¿Y ésto a cuento de qué?. Pues como algunos habréis imaginado (y si no lo habéis imaginado yo os lo cuento), si en cada lectura que realiza nuestro procesador leemos 4 bytes y un short son 2 bytes, tendremos que colocar dicha variable bien en los dos primeros bytes o bien en los dos últimos. Por supuesto también podríamos colocarlo en los bytes 2 y 3, pero si permitimos ese tipo de cosas nada impediría que el primer byte de un short cayese en el último byte de una palabra leída y el segundo en el primer byte de la palabra siguiente. Mas claramente: nuestra máquina lee las direcciones 0×0000, 0×0004, 0×0008, etc…. Nuestro short correría el riesgo de caer entre las direcciones 0×0003 y 0×0004. ¿Cual es la pega de ésto? Obviamente que el procesador debería realizar dos lecturas a memoria: una a la dirección 0×0000 y otra a la dirección 0×0004 para recuperar los dos “trozos” de short. Ahora se ve claro por qué hace falta definir ésto del alineamiento de los tipos de datos: Ahorra trabajo y tiempo al procesador.
Decimos entonces que un short está alineado a dos bytes.

Como podremos imaginar, para el caso de un int o incluso de un double, la alineación tiene que ser forzosamente a 4 bytes, es decir, deben de estar almacenados en direcciones múltiplos de 4.

Ahora si, el Padding

Muy bien, ahora que ya hemos entendido en qué consiste la alineación, podemos hablar del Padding, que no es ni mas ni menos que bytes de “relleno” que se utilizan para forzar el alineamiento de los miembros de una estructura, en el caso del lenguaje C. Veamoslo con un ejemplo:
En el siguiente código podemos ver que tenemos definida una estructura formada por un char y un int:

  1. #include <stdio.h>
  2.  
  3. int main (int argc, char** argv){
  4.  
  5.   struct {
  6.     char a;
  7.     int b;
  8.   } padding;
  9.  
  10.   char* p = (char *)&padding;
  11.  
  12.   padding.a = ‘z’;
  13.   padding.b = 0x6fabada6;
  14.  
  15.   printf("longitud de padding: %i\n", sizeof(padding));
  16.   printf("Datos originales:\n\ta —> %c\n\tb —> 0x%x\n", padding.a, padding.b);
  17.  
  18.   *p = ‘a’; p++;
  19.   *p = 0xbe; p++;
  20.   *p = 0xba; p++;
  21.   *p = 0×12; p++;
  22.   *p = 0×34;
  23.  
  24.   printf("Datos modificados:\n\ta —> %c\n\tb —> 0x%x\n", padding.a, padding.b);
  25. }

Antes de compilar ni ejecutar nada podemos suponer que el tamaño de nuestra estructura (en una máquina de 32 bits) debería ser de 5 bytes: 4 bytes del int y 1 del char. El código simplemente imprime la longitud de la estructura, los datos originalmente almacenados en ella y después, a través de un puntero char recorre dicha estructura y modifica los datos. Finalmente, vuelve a imprimir los datos guardados en la estructura.
Ahora ya podemos compilarlo y ejecutarlo obteniendo la siguiente salida:

  1. longitud de padding: 8
  2. Datos originales:
  3.         a —> z
  4.         b —> 0x6fabada6
  5. Datos modificados:
  6.         a —> a
  7.         b —> 0x6fabad34

:-| ¿qué ha pasado? ¿y esa longitud 8 en lugar de 5? Sencillo: nuestra máquina es de 32 bits. Para poder forzar el alineamiento correcto de las variables que componen la estructura tiene “rellenar” el hueco ocupado entre el char y el int para que éste último comience en una dirección múltiplo de 4 (o en el caso de un PC de 32 bits, se lea en la siguiente dirección de memoria, porque en éste caso, el bus de la memoria coincide con el del micro). Es decir, es como si hubiésemos declaro padding de ésta otra forma:

  1. struct {
  2.   char a;
  3.   char dummy1;
  4.   char dummy2;
  5.   char dummy3;
  6.   int b;
  7. } padding;

de modo que dummy? son solo para rellenar (padding) y hacer que b empiece donde debe, respetando así el alineamiento. Si no fuese así y quisiéramos acceder a a, seguiríamos usando una lectura, mientras que para acceder a b la cosa cambiaría, ya que necesitaríamos una lectura para acceder a los tres primeros bytes y una segunda lectura mas para acceder al último. Después habría que realizar desplazamientos y ajustes para obtener el valor final.
De ahí que veamos otro efecto colateral a la salida de la ejecución del código: El último valor leído de b no coincide con el esperado. De hecho solo hemos modificado el primer byte. Los otros tres bytes que hemos recorrido han sido los del padding.

Ésto abre la veda para hacer pequeños “experimentos”. Por ejemplo, si cambiamos a y b de posiciones relativas veremos que el tamaño sigue siendo 8. ¿De verdad sigue haciendo falta relleno? Ahora se supone que leemos primero el int y que por tanto b lo podremos leer sin problemas…. Pues la respuesta es si y no. En realidad ahora no hay padding, pero si que es cierto que la estructura sigue ocupando 8 bytes en memoria, pues tendremos que hacer dos lecturas para acceder a todos sus miembros.

Pero podemos hacer mas cosillas: Por ejemplo, podemos declarar otro miembro de tipo short entre a y b y ver qué pasa con el tamaño. ¿Ha cambiado? ¡¡NO!! ¿y eso?. Pues porque al encontrarse el short entre un char y un int, puede utilizar tres de los bytes de padding para almacenarse, por lo que ahora habrá un padding de un solo byte. Si en lugar de eso declaramos el short después de b, veremos que la cosa cambia bastante. Ahora estaremos usando 12 bytes. Queda bastante claro todo ésto ¿no?.

Evitando el padding con GCC

Una pregunta bastante obvia que puede asaltar a cualquier lector es: ¿y si no quiero que haya padding porque me hace desperdiciar memoria o me viene fatal para recorrer mi estructura?. Bueno, GCC permite forzar el padding que nosotros queramos usando pragmas. En concreto se usa el pragma pack. Veámoslo con un ejemplo sobre nuestro código anterior:

  1. #include <stdio.h>
  2.  
  3. int main (int argc, char** argv){
  4.  
  5. #pragma pack(push,1)
  6.   struct {
  7.     char a;
  8.     int b;
  9.   } padding;
  10. #pragma pack(pop)
  11.  
  12.   char* p = (char *)&padding;
  13.  
  14.   padding.a = ‘z’;
  15.   padding.b = 0x6fabada6;
  16.  
  17.   printf("longitud de padding: %i\n", sizeof(padding));
  18.   printf("Datos originales:\n\ta —> %c\n\tb —> 0x%x\n", padding.a, padding.b);
  19.  
  20.   *p = ‘a’; p++;
  21.   *p = 0xbe; p++;
  22.   *p = 0xba; p++;
  23.   *p = 0×12; p++;
  24.   *p = 0×34;
  25.  
  26.   printf("Datos modificados:\n\ta —> %c\n\tb —> 0x%x\n", padding.a, padding.b);
  27. }

El primer pragma establece que se fuerce un padding de 1 byte y lo “apila” en una pila que usa el compilador. De ésta forma podemos ir forzando varios paddings y cuando se use pragma pack(pop) sacaremos el último padding que hayamos usado y volveremos al anterior. En nuestro caso, volveremos al padding por defecto de nuestra máquia, puesto que solo hemos hecho un push.

Si ahora ejecutamos el código veremos que si que sucede lo esperado: padding ocupa 5 bytes y recorriendo la estructura con un puntero a char conseguimos modificar todos los datos como esperábamos.

Yo personalmente opto por no “forzar” las cosas. Un consejo para definir estructuras es ir declarando sus componentes por orden de menor a mayor tamaño. De ésta forma, quedarán organizados de una forma bastante óptima. También habrá que cuidar los recorridos por los miembros de la estructura, utilizando funciones específicas para ello.

Claro que también puede haber situaciones en las que no quede mas remedio. Por ejemplo, otra cosa en la que actualmente ando liado es la implementanción de un pequeño driver para un sistema de archivos FAT32 que deberá correr en microcontroladores AVR con muy pocas capacidades. Para poder interpretar las tablas de asignación de archivos he de leer bloques del medio en el que tengo almacenados los datos y después interpretar esa información acorde a la estructura que define a dicha tabla. El problema me viene, al igual que comenté al comienzo de ésta entrada, en que si bien en el caso del microcontrolador (con un bus de 8 bits) los datos leídos casan perfectamente con las estructuras necesarias, para el caso de los tests en el PC esto no es así, ya que las estructuras utilizan muchos tipos de 8 y 16 bits y el padding generado para forzar el alineamiento hace que los datos leídos no concuerden con los campos a los que tienen que ir a parar. En éste caso, tengo dos opciones: o una vez leído el bloque (y guardado temporalmente en un array de char) voy rellenando todas las estructuras campo a campo (algo muy muy lento para un microcontrolador y que necesita gran cantidad de código) o bien fuerzo el alineamiento a un byte para evitarme el padding y genero un puntero a la estructura que me interesa guardando en él la dirección de comienzo de mi array a char. De ésta manera podré recorrer mas fácilmente la estructura, sabiendo que para el micro no supondrá coste alguno y que para el PC generaré algo de código extra (al tener que forzar el alineamiento), pero realmente como mi intención es usar el PC sólo para validar los algorítmos, no importa que sea algo ineficiente si con ello consigo el efecto deseado.

Bajo mi punto de vista (y por lo que acabamos de ver también), creo que forzar paddings puede suponer que en algunas arquitecturas el procesador tenga que realizar mas trabajo. En un PC puede que sea (o no) despreciable, pero desde luego en un sistema empotrado ello supone pérdida de tiempo, consumo de energía y consumo de memoria de código (necesitaremos mas código para codificar las operaciones, como es lógico suponer). Ya es decisión de cada uno optar por una u otra forma de implementar.

Referencias

Pues como siempre, navegando por Internet uno encuentra muchas cosas. En http://bytes.com/topic/c/answers/543879-what-structure-padding encontré una explicación bastante clara de todo ésto del alineamiento y del padding.

Errores en la post instalación de paquetes en entornos Debian

0
Filed under GNU, General
Tagged as , ,

Muchas veces me ha pasado que instalando paquetes se han producido fallos debidos a que la “post instalación” no se ha efectuado correctamente. En estos casos, dpkg falla, dejando cualquier paquete que quede pendiente sin terminar. Ésto hace que además cualquier intento tanto de instalar como de desinstalar paquetes falle.

Una forma bastante tosca pero efectiva de solucionar ésto es acceder al script de postinstalación correspondiente y editarlo para que devuelva el valor esperado (generalmente 0). Como ya estoy harto de que siempre se me olvide donde están guardados esos archivos, aquí pongo la ruta.

  1. /var/lib/dpkg/info/paquetito.postinst

Éste archivo corresponde al script de postinstalación del paquete paquetito. Lo único que hay que hacer es que éste paquete devuelva el valor 0 y con ello la instalación podrá finalizar correctamente.

udev: Configurando el acceso al USB sin ser root

0
Filed under GNU, General
Tagged as

Introducción

A veces sucede que quieres utilizar un dispositivo USB un poco “exótico” y resulta que no puedes utilizarlo sin ser root. Un ejemplo de ello puede ser dfu-programmer o pk2, que son aplicaciones no muy estándard y por lo tanto no se les ha dado el soporte necesario, haciendo que haya que invocarlas como root si queremos utilizarlas.

La solución para ésto pasa por crear unas reglas para udev que permitan que éstas aplicaciones accedan al puerto USB de nuestro PC en modo normal.

Un ejemplo: dfu-programmer

Ilustraré el proceso con una aplicación de ejemplo: dfu-programmer. Se trata de un cliente para el bootloader USB instalado en los micros con soporte para dicho interfaz de Atmel.
Para añadir las reglas, abrimos (mas bien creamos) el archivo que contedrá dichas reglas:

  1. yo@miMaquina:~$ sudo emacs /etc/udev/rules.d/99-dfu-programmer.rules

En este archivo, deberemos escribir algo tal que así:

  1. SUBSYSTEM=="usb", ACTION=="add", SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2ffb", MODE="660", GROUP="plugdev", SYMLINK+="at90usb-%k"
  2. BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2ffb", MODE="660", GROUP="plugdev"

Básicamente lo que se hace es indicar a udev que dfu-programmer usa el sistema USB, dando información detallada acerca del vendorID y el productID del dispositivo que se va a conectar al puerto. También indica con qué permisos se debe acceder al puerto y especifica el grupo cuyos permisos hereda la aplicación.

Referencias

NOTA: Entrada extraída de otra antigua entrada publicada por mi en CrySoL.