domingo, 22 de noviembre de 2009

Google lanza Chrome OS

Google acaba de presentar su nuevo sistema operativo Chrome OS.



La empresa plantea su nuevo sistema operativo, no como un sustituto de los actuales, sino como un sistema operativo destinado a un sector especifico de los usuarios de Internet que demandan sistemas Netbook cada vez mas faciles de usar. La empresa rentabilizará este proyecto con creces, puesto que se trata del sector con mas numero de usuarios de la red, y aumentando a un ritmo exponencial según sus estudios.

Esos usuarios no necesitan saber nada de procesos, de gestion de memoria, de planificadores, de interrupciones, comunicaciones, drivers, concurrencia, lenguajes de programación, administracion de sistemas, redes, etc. Son usuarios que quieren un equipo facil de usar, que arranque rapido y que dispongan de todas las aplicaciones que usan habitualmente: email, web browser, facebook, chat, juegos, youtube, etc.

Google define estos tres requisitos (3S) como los requisitos basicos de su nuevo sistema operativo:

1S. Security (seguridad):
Quieren que el sistema sea seguro, libre de malware, y para ello nada mas facil que montar el rootfs del sistema en modo solo lectura y que todas las aplicaciones que use el usuario se encuentren en lo que se denomina "la nube" (una metafora de Internet), y no como copias locales en su propio PC. Una consecuencia de esto es que los propios datos del usuario (fotos, documentos, videos...) no podran almacenarse en el sistema, sino que tambien se almacenan en "la nuve". Ellos argumentan que es mas seguro que almacenar los datos en nuestro propio PC, ya que la perdida o robo del Netbook, implica la perdida total de los datos, mientras que en la nuve siempre estarán disponibles desde cualquier PC desde cualquier parte del mundo.

2S. Speed (velocidad):
Quieren que el arranque del sistema sea rapido. Para ello, el hardware del Netbook solo dispondrá de una pequeña memoria flash para almacenar al Chrome OS. Como carece de disco duro (mecánico = lento), la velocidad de arranque aumenta considerablemente. Pero ademas, ellos siguen trabajando con el software del sistema operativo, intentando reducir todavía mas el tiempo de arranque de un sistema operativo convencional. Actualmente su sistema arranca en 7 segundos. Su objetivo es conseguir un dispositivo que arranque tan rapido como un televisor, pulsando el boton de Power e inmediatamente mostrando el login del sistema.

3S. Simplicity (simplicidad):
Quieren que el sistema operativo sea simple de usar, y para ello usan el navegador Chromium como escritorio del Netbook. A partir del navegador se pueden lanzar todas las aplicaciones que usa comunmente el usuario: web browser, reproductor multimedia para audio y video, juegos online, aplicaciones ofimaticas como el Google Docs, etc. Se olvida el concepto de administracion del equipo: ya no hay que mantener actualizados drivers, ni paquetes del sistema operativo, ni antivirus, todo este trabajo deja de ser necesario para el usuario.

A nivel de arquitectura, estaría el sistema operativo Chrome OS controlando el hardware del Netbook, y por encima unicamente el Chromium browser como interfaz de usuario, sobre el cual correrían el resto de las aplicaciones.

                        +------------------------+
                        |         ...            |
                        |       Twitter          |
                        |       Facebook         |
                        |        Gmail           |
                        |       Blogspot         |
                        |     Search engine      |
                        |      Google maps       |
                        |      Google docs       |
                        |      Google knols      |
                        +------------------------+
                        |    Chromium browser    |
                        +------------------------+
                        |       Chrome OS        |
                        +------------------------+
                        |       Netbook HW       |
                        +------------------------+

Resumiendo, Chrome OS es el sistema operativo para la gente que no sabe lo que es un sistema operativo (o como mi amigo Jose, que lo sabe, pero prefiere olvidarse de ello :-) Los sistemas operativos tradicionales tal y como los conocemos hoy en día, seguirán siendo la herramienta para los profesionales del medio: desarrolladores de software y administradores de sistemas. El resto de los usuarios estaran usando el sistema operativo Chrome OS, muy posiblemente desconociendo su propia existencia.

Creo que Google va a facilitar las vidas de usuarios e ingenieros, consiguiendo que los sistemas operativos tal y como los conocemos hoy en día, sean una herramienta exclusiva de los profesionales del medio. Los usuarios no tendrán que pelear con conceptos complejos que no les interesan en absoluto, y los ingenieros, por fin, dejaremos de ser los pringaos del howto.

sábado, 7 de noviembre de 2009

Metodo Cesar y analisis de frecuencias

Hace poco compré el libro "Redes Privadas Virtuales" de la editorial Ra-Ma, escrito y publicado por mi buen amigo Javi (aprovecho para hacerte un poco de publicidad jejeje). Leyendo el principio del capitulo 3 sobre criptografía, recordé mis inicios en la criptografía cuando cursé en la UJI allá por 2º de carrera la asignatura de "Seguridad y Protección de la información" bajo la supervisión del Dr. Manuel Mollar, un crack en temas de seguridad donde los haya, del que aprendí todo lo que sé hoy en día sobre criptografía.

Entre unos y otros he terminado por animarme a escribir este post sobre criptosistemas y criptoanalisis que resultará bastante entretenido para la gente curiosa que guste de estos temas.

Primero unas formalidades para centrar el asunto sin enrollarnos demasiado: definiremos criptologia como la suma de dos ciencias que se complementan: criptografia y criptoanálisis.

La criptografia diseña algoritmos que permiten comunicaciones secretas entre un emisor y un destinatario. En la criptografia clasica intervienen dos factores: un algoritmo de cifrado y una clave secreta, K.

                     ----cifrado(K)---->
Mensaje en claro Mensaje cifrado
<--descifrado(K)---


El criptoanálisis se encarga de elaborar tecnicas que permiten descubrir tanto el algoritmo de cifrado utilizado como la clave secreta involucrada en el proceso de encriptado.

    Mensaje cifrado --- ¿algoritmo + K? ---> Mensaje en claro


Vamos a explicar como funciona un criptosistema muy sencillo, conocido como método de Cesar (usado hace unos cuantos años en las campañas militares romanas), y tambien vamos a ver lo facil que resulta atacarlo mediante una sencilla técnica de criptoanálisis conocida como el análisis de frecuencias.



El algoritmo de cifrado es muy sencillo. Cada caracter del mensaje en claro es sustituido por el situado K > 0 posiciones mas adelante en el alfabeto. Por ejemplo, asumiendo K=3, el criptosistema reemplaza la A por la D, la B por la E, y así sucesivamente. El descifrado es igual de facil, ya que consiste en sustituir cada caracter del mensaje cifrado por el situado K posiciones atras en el alfabeto.

Ejemplo de cifrado de Cesar con K = 4

    Mensaje: E L P E R R O D E S A N R O Q U E T I E N E R A B O
Clave: 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
Cifrado: I P T I V V S H I W E R V S U Y I X M I R I V E F S


Aqui teneis un codigo escrito en C cesar.c que os permitira encriptar y desencriptar cualquier documento con la clave K que paseis como argumento de entrada:

/* Algoritmo de Cesar con clave k */

int main (int argc, char **argv)
{
/* argumentos de entrada */
if (argc != 3) {
printf("syntax: %s -[e|d] key\n", argv[0]);
printf("example: %s -e 3\n", argv[0]);
exit(0);
}

if (argv[1][1] != 'e' && argv[1][1] != 'd') {
printf("syntax: %s -[e|d] key\n", argv[0]);
exit(0);
}

/* inicializaciones */
char ed = argv[1][1]; /* encode o decode */
int k = atoi(argv[2]); /* key */
if (k > 255)
k = k % 256;

char c;

/* encoding ... */
if (ed == 'e') {
while (read(0, &c, sizeof(unsigned char)) > 0)
printf("%c", (c + k) % 256);
}

/* decoding ... */
if (ed == 'd') {
while (read(0, &c, sizeof(unsigned char)) > 0)
printf("%c", (c - k) % 256);
}

return 0;
}


El criptosistema de Cesar es facilmente atacable usando una tecnica de criptoanalisis conocida como analisis de frecuencias, ya que la frecuencia de aparicion de cada letra en el mensaje en claro se refleja exactamente en el texto cifrado. Conociendo la letra de mayor frecuencia en el alfabeto utilizada, queda automaticamente establecida la correspondencia.

Vamos a atacar un mensaje cifrado con Cesar usando analisis de frecuencias. Sea por ejemplo el siguiente texto en castellano cifrado con una clave K, de momento desconocida. Nuestro objetivo es averiguar la clave K para descifrar el contenido del siguiente mensaje:

hqxqoxjdughodpdqfkdghfx|rqrpeuhqrtxlhurdfrugduphylyldxqorfrpdfduudtxhwrfdedodjxlwduud


Saber que el texto está en castellano es una pista muy clara de que debemos usar una tabla de frecuencias en castellano. En esta direccion teneis la tabla completa de la frecuencia de aparición de cada carácter en el idioma que mas os interese. En la tabla de castellano podremos encontrar que el caracter mas usado en nuestro idioma es el caracter 'e'.

Ahora necesitamos un programa que calcule la frecuencia de aparicion de cada caracter ASCII en el texto cifrado. Para ello hemos desarrollado este pequeño programa freq.c en C.

/* Frecuencia de cada caracter ASCII */

int main(int argc, char **argv)
{
/* inicializaciones */
unsigned long int total = 0;
float freq = 0;

int i;
int ascii[256]; /* numero de apariciones de cada ascii[i] */
for (i = 0; i < 256; i++)
ascii[i] = 0;

unsigned char c;

/* actualizacion de la tabla ascii y de la variable total */
while (read(0, &c, sizeof(unsigned char)) > 0 ) {
ascii[c]++;
total++;
}
close(0);

/* visualizacion resultados tabla ASCII */
for (i = 0; i < 256; i++) {
if (ascii[i]) {
freq = ((float) ascii[i]) / ((float) total);
printf("ASCII[%d] = %d\tfreq = %f\n", i, ascii[i], freq);
}
}

/* visualizacion total */
printf("\nTotal of characters: %lu", total);
printf("\n");

return(0);
}


El resultado aplicado sobre el texto cifrado es el siguiente:

ASCII[100] = 15 freq = 0.176471
ASCII[117] = 9 freq = 0.105882
ASCII[114] = 8 freq = 0.094118
ASCII[104] = 7 freq = 0.082353
ASCII[120] = 7 freq = 0.082353
ASCII[102] = 6 freq = 0.070588
ASCII[113] = 6 freq = 0.070588
ASCII[108] = 4 freq = 0.047059
ASCII[111] = 4 freq = 0.047059
ASCII[112] = 4 freq = 0.047059
ASCII[103] = 3 freq = 0.035294
ASCII[101] = 2 freq = 0.023529
ASCII[106] = 2 freq = 0.023529
ASCII[116] = 2 freq = 0.023529
ASCII[119] = 2 freq = 0.023529
ASCII[121] = 2 freq = 0.023529
ASCII[107] = 1 freq = 0.011765
ASCII[124] = 1 freq = 0.011765

Total of characters: 85


Si el caracter mas frecuente en español es la letra 'e' (ascii 101), sabemos que alguno de los caracteres mas frecuentes del texto cifrado corresponde con la letra 'e'. Solo nos queda ir probando en secuencia las posibles claves hasta dar con una que decodifique el texto cifrado y nos deje ver con claridad el contenido del texto cifrado. Por tanto, debemos ir probando con esta secuencia de claves K:

    MAX   'e'
------------------
K = 100 - 101 = -1
K = 117 - 101 = 16
K = 114 - 101 = 13
K = 104 - 101 = 3
K = 120 - 101 = 19
...


Ningun texto cumple al pie de la letra con las frecuencias características del lenguaje (es un tema estadístico), aunque podeis estar seguros que la probabilidad de que el caracter 'e' sea uno de los caracteres mas frecuentes, es muy alta.

¿Quien será el primero en dejarme un comentario con el resultado del texto en claro?

Existen varios concursos planteados por distintos organismos oficiales como la CIA y conocidísimas empresas todopoderosas como Google con el proposito de cazar talentos dispersos por esos mundos...



En los exteriores de las oficinas de la CIA en Langley (Virgina) se encuentra una escultura enorme de bronce, de unos cuatro metros de altura, conocida como kryptos, en la que se esconden cuatro mensajes cifrados escritos en ingles. La primera persona que anunció publicamente haber resuelto los tres primeros fue James Gillogly, y por lo que se sabe, la cuarta parte continua sin resolver.



En las paredes del MIT aparecieron carteles de Google con este críptico mensaje acompañado del texto "si puedes averiguar esto, puedes tener futuro en Google". El mensaje encriptado contiene un número de teléfono al que llamar en caso de acertarlo.

Para resolver estos criptosistemas, necesitareis investigar por vuestra cuenta sobre otros criptosistemas por trasposicion como el Vigenere, una variante del metodo de Cesar que usa cadenas de texto como clave. Y tambien los criptosistemas por sustitucion, que unicamente reordenan la posicion de los mensajes en el texto. Y sobre variantes de unos y otros, incluso combinadas entre si. Asi que manos a la obra... ¿Os veis con ganas de intentar trabajar... en Google ... o en la CIA? Yes you can! Why not! :-)

miércoles, 7 de octubre de 2009

La ciencia española no necesita tijeras...

El Gobierno baraja una reducción del 37% del dinero destinado a financiar los proyectos de I+D, las becas y los contratos de investigadores, para caer a los niveles de 2006.

Muy bonito señores gobernantes de este país, es fabuloso. Los bancos piden ayudas millonarias al gobierno para afrontar una crisis que ellos mismos inician (por pura avaricia), nuestros señores gobernantes se las condecen para que puedan auto-regalarse pensiones vitalicias millonarias (son empresas privadas, cierto, pero reflotadas con dinero público... con el dinero de nuestros impuestos).

La industria del automovil pide ayudas millonarias porque se reducen las ventas y no alcanzan sus previsiones de crecimiento, (pobrecitos, que no han ganado bastante con los millones de vehiculos que colapsan las carreteras españolas a cualquier hora punta del día), ayudas que les llegan.

Que los paletas de este pais se quedan sin trabajo despues de estallar la burbuja inmoviliaria en la que ganaban mensualmente el sueldo de dos ingenieros, y les daba para construirse su propia casas a precio de coste en un par de años... Pues ayudas para que los paletas arreglen aceras... Mientras otros españoles (todos ellos con los mismos derechos según la Constitución española) se ven obligados a hipotecar su vida con algún banco, durante 30, 40 y hasta 50 años...

¿Y quien va a pagar las consecuencias de los excesos cometidos? Desde luego, todos los españoles, con el anunciado incremento del iva, que cuando interesa... "todos somos iguales" y que "hacienda somos todos", etc. "Todos debemos ser solidarios", eso nos dicen ahora. Supongo que esos que manejan millones diariamente deberían ser igual de solidarios que todos, igualdad en terminos relativos... a su salario neto, señores gobernantes, eso es lo que queremos los ciudadanos, y que no nos tomen mas el pelo.

"Todos los ciudadanos españoles tienen derecho a una vivienda digna". Pero por lo visto la vivienda no es un bien de primera necesidad, pues está grabada con un iva del 7%. Y que a un mileurista le digan que tiene que ser solidario y pagar 1000 euros mas de iva al comprar una vivienda de 40m2 para vivir con su familia... (que en realidad no son 1000 sino 2000 euros, porque de esos 1000 euros de iva tambien hay que pagar los intereses al banco durante los 30 años de la hipoteca), eso, eso es fomentar la solidaridad, eso es.

A esos millonarios (de euros, no de pesetas), "no les podemos subir mas los impuestos, no sea cosa que se lleven su dinero a otro pais". Y me pregunto yo, qué problema habrá con que ese dinero se vaya a otro país, ¡si el dinero seguirá siendo suyo vayan donde vayan! ¿Quizás sus "regalos" son mas atractivos que los mios?.

Pero especialmente afectados se verán los científicos e investigadores, que parece ser que para lo inteligentes que son, aprovechan muy poco sus cualidades intelectuales para sacar beneficio propio (gracias a dios, y por el bien de la ciencia, mejor que mantengan ocupados sus cerebros en cosas mas trascendentales), porque por lo visto no sacan tajada nunca, ni cuando las cosas van bien, ni menos aún cuando van mal.



Quiero recalcar lo duro que resulta cursar estudios universitarios de ciencias, esfuerzo que por meritos propios debería garantizar al individuo que los afronta con éxito un futuro próspero y mas estable. Los científicos deben costearse unos estudios universitarios e hipotecar su vida personal por un periodo mínimo de 5 años de carrera universitaria (y muchos saben, sobre todo los implicados, que resulta muy pero que muy complicado completarlos en ese tiempo). Otros, como los médicos, incluso hasta 10 años pagandose los estudios y sin cobrar ni un misero céntimo. ¿Y todo ese esfuerzo economico y personal para llegar a donde?

La compensación que les ofrece el gobierno parece humillante... Lo que les tocará es reducir sus salarios o matar proyectos de investigación en los que llevaban años trabajando, para poder pagar impuestos necesarios para rescatar a bancos o a industrias del automovil, y solidarizarse con esa gente parada con escasa cualificación que estan perdiendo sus puestos de trabajo diariamente (miles). Y que mientras esos parados (muchos de ellos felices de su condición) viven en sus casitas a cuerpo de rey, cobrando el subsidio de desempleo y dándose unas buenas vacaciones, incluso rechazando ofertas de trabajo que "no les gustan", (hablo con conocimiento de causa) mientras los cientificos y sus proyectos pagan los excesos cometidos por unos y otros.

Señores politicos, con este apoyo a los cientificos, y viendo los beneficios obtenidos despues de tanto sacrificio, lo que van a conseguir es que en pocos años, este pais se convierta en un pais de analfabetos incultos esperando nuevas ayudas para cobrar la prestación por desempleo. Cualquiera diría que esta situación les interesa incluso más que tener un pais de gente competente, no sea que les pongan las cosas dificiles en su labor de gobernar.

Si investigan un poco podrán ver la tendencia decreciente en matriculaciones en carreras de ciencias en los últimos años, lo que demuestra que estamos en el buen camino. Que alguien me explique como piensan sostener este pais haciendo lo que estan haciendo. Sin investigación no hay productos nuevos. Sin productos nuevos no hay produccion. Sin produccion la gran masa social se queda desempleada. Sin trabajadores, el estado reduce sus ingresos... Poco a poco la piramide se desmorona, y a este paso caeremos todos, desde el primero hasta el último.

No se olviden de una cosa, sus hijos son los que pagarán las consecuencias mas graves. Aunque posiblemente eso también les debe importar muy poco... porque el largo plazo que mas les preocupa seguramente no llegue mucho mas allá de la fecha marcada por las próximas elecciones.

Esta es la realidad del pais en el que vivimos muchos científicos.

sábado, 3 de octubre de 2009

Kernel boot process para novatos

El usuario de un PC pulsa el boton de alimentación del sistema (power) y espera su arranque hasta que se muestre en pantalla el interfaz de usuario gráfico donde el sistema solicita usuario/password para iniciar la sesion. Este post profundiza en ese proceso de arranque, con la intención de que cualquier lector con los conocimientos suficientes, entienda mejor todos los pasos involucrados, sin entrar en detalles que dificulten su comprensión.

En resumen, desde el power-on hasta el login del usuario, se pasa por 4 etapas:
1.- Programa en ROM carga el boot-loader
2.- El boot-loader carga el kernel
3.- El kernel inicializa el sistema y pasa el control al user-space
4.- El user-space finaliza la inicializacion.


Etapa 1. La BIOS

Tras el power-on, un pequeño programa cargado en ROM toma el control del sistema (la BIOS en x86).

Este pequeño programa localiza el "boot device" con el que arrancar el sistema, y para ello elige el primer dispositivo bootable disponible en la secuencia "boot order" (por ejemplo, primero con CD/DVD, despues con USB y despues con HD). Una vez conocido el dispositivo bootable, lee su MBR (sector 0). Este MBR almacena 3 cosas: la rutina bootstrap loader (en .asm), la tabla de particiones y la firma de dispositivo bootable (0x55AAh) como dos ultimos bytes de la partición. Por último, el pequeño programa cargado en ROM pasa el control de ejecución a la rutina bootstrap loader, hecha única y exclusivamente para pasar el control al boot-loader.


Etapa 2. El boot-loader

Los ejemplos mas comunes de boot-loader son grub y lilo (x86, amd) y u-boot (arm). Lo típico es que el boot-loader presente al usuario un menu con las distintas opciones de arranque (diferentes sistemas operativos, distintos kernels del mismo sistema operativo, o programas que no necesiten de sistema operativo como memtest86+). Normalmente tienen una opcion seleccionada por defecto mas un timeout. El usuario elige una de las opciones o el timeout elige la opcion por defecto.

El boot-loader carga el kernel seleccionado en RAM, y opcionalmente tambien la imagen initramfs. La pregunta es, ¿y como accede el boot-loader a la imagen del kernel guardada en el filesystem de una de las particiones...? ¡Sin soporte del kernel!. Cada boot-loader resuelve este problema de forma diferente. El lilo por ejemplo necesita conocer la localizacion exacta del sector del disco en el que esta la imagen del kernel. Grub, en cambio, entiende muchos sistemas de fichero (ffs, fat16, fat32, minic, ext2, reiserfs, jfs, xfs y vst), y puede leer ficheros en dichas particiones sin ayuda de nadie.

Finalmente, el boot-loader pasa el control de ejecución al kernel cargado en RAM, pasandole tambien su lista de argumentos argv (como se hace con cualquier otro programa escrito en C).

Arranque directo vs arranque encadenado

El grub boot-loader permite dos tipos de arranque: directo y encadenado. El arranque directo permite arrancar directamente un sistema operativo (Linux). En arranque encadenado (chain-loading), permite arrancar otro boot-loader distinto (el que usa Windows).

Para arrancar un sistema operativo, el grub necesita conocer el dispositivo de almacenamiento y la partición de ese dispositivo en el que se encuentra almacenado su kernel. Además, en modo directo tambien necesita el path al binario del kernel al que transfiere el control. Mientras que en modo encadenado, transfiere el control al PBR (Partition Boot Record) de la partición indicada; se trata de un bloque similar al del MBR pero almacenado en la partición. Esta dualidad posibilita a grub el arranque del cualquier sistema operativo, sea libre o propietario.

El fichero de configuración del grub

El fichero de configuracion del grub se llama menu.lst y generalmente se encuentra en el directorio /boot/grub/. Cuando grub arranca, lee su contenido y presenta al usuario un menu con las opciones de arranque disponibles en su interior.

Algunas etiquetas para definir parametros generales de su configuración:
- default - Establece la entrada (title) seleccionada por defecto
- timeout - Tiempo en segundos para arrancar la configuracion default
- splashimage - Imagen de fondo (14 colores, 640x480, .xpm.gz)

Por ejemplo:
default 1
timeout 3
splashimage=(hd0,0)/boot/grub/splash.xpm.gz

Por cada sistema operativo que grub puede arrancar, se define en menu.lst un grupo de etiquetas que especifican toda la información que grub necesita para poder arrancarlo. Cada grupo de etiquetas se inicia con la palabra clave "title", que especifica el texto mostrado para el sistema operativo arrancado, y a continuación una serie de etiquetas que dependen del modo de arranque (directo o encadenado). Veamos dos ejemplos para entenderlo mejor:

Ejemplo tipico Linux (carga directa)
title       Ubuntu, kernel 2.6.22.5-custom
root (hd0,0)
kernel /boot/vmlinuz-2.6.22.5-custom root=/dev/hda1 ro quiet splash
initrd /boot/initrd.img-2.6.22.5-custom
boot

Ejemplo tipico Windows (carga encadenada)
title       Windows Vista
root (hd0,1)
chainloader +1

Las etiquetas tipicas de estas entradas son:
- title - Texto mostrado para el sistema operativo arrancado
- root - Dispositivo de almacenamiento y particion donde esta disponible el kernel.
- kernel - (Carga directa) Path en root a la imagen del kernel arrancado
- initrd - (Carga directa) Path en root al fichero initramfs
- boot - (Carga directa) Arranca el sistema operativo seleccionado
- chainloader - (Carga encadenada) Pasa control al sector del PBR indicado

La etiqueta "root" confunde a mucha gente (y no es para menos). La sintaxis es propia de grub, no la confundais con la sintaxis de los ficheros dispositivo situados en /dev para los dispositivos de almacenamiento, que diferencia los dispositivos de almacenamiento IDE (hda) de los SCSI (sda). En cambio, grub usa siempre el prefijo hd. Por tanto, (hd0,0) significa primer bootable-device (0) de la primera partición (0), mientras que (hd1,3) significa segundo bootable-device (1) de la cuarta partición (3). Tampoco olvideis que el bootable-device depende del boot-order asignado en la BIOS.


Etapa 3. El kernel de Linux

El kernel toma el control del sistema: se descomprime a si mismo, inicializa el hardware (CPU, cache y configuración específica de cada board), los distintos subsistemas del kernel (el scheduler, el gestor de memoria, y los sistemas de ficheros virtuales /proc y /sys, sin llegar a montarlos). A continuación lee su lista de argumentos argv. Algunos parámetros tipicos de argv son estos:

- root=/dev/sda1 - Fichero dispositivo de la particion raiz ("/")
- rootfstype=ext2 - Sistema de ficheros de la particion raiz
- init=/sbin/init - Primer programa del user-space ejecutado
- Muchos mas en Documentation/kernel-parameters.txt

A continuación inicializa la consola (/dev/console) para poder mostrar los logs del arranque por pantalla. Y por fin monta su partición raiz (root). Este es el paso mas importante para los usuarios, y se explica despues con mayor detalle.

El kernel intenta ejecutar el primer programa del user-space (init). Para ello, crea un kernel-thread que se reemplaza a si mismo (syscall execve) con la imagen del binario del userspace apuntado por init (normalmente apuntando a /sbin/init). Si el programa indicado por init no se encuentra en la particion raiz, el kernel muestra un panic error indicando el error. Si lo encuentra, pasa el control a dicho programa.

Recordemos que este binario reside en la particion raiz (root). Se trata del primer programa del user-space ejecutado, y el primer programa compilado con la libreria de C estandar (libc).

Montaje de la partición raiz

Para montar la partición raiz (root), el kernel necesita el device driver del dispositivo que aloja la partición raiz y el driver del sistema de ficheros de esa partición (ext2, ext3, etc.).

Si esos 2 drivers fueron compilados built-in (no como modulos), el kernel dispone de todo lo necesario para montar la partición raiz. Por tanto la monta y completa su trabajo.

Si los drivers fueron compilados como modulos (no built-in), el kernel necesita extraer esos modulos de algun sitio. Para ello se usa la imagen initramfs de la que ya hemos hecho algun comentario en este post (profundizaremos sobre ella despues). El kernel lee la imagen initramfs cargada en RAM por el bootloader, la descomprime y monta el sistema de ficheros almacenado en su interior. Continua ejecutando el script /init almacenado en el initramfs. Desde ese script podemos lanzar el código que mas nos interese:

- Una opcion es que /init monte la partición raiz indicada en (root). Para ello lee de initramfs los modulos necesarios para montar el dispositivo indicado en root, carga dichos modulos y reemplaza el montaje del initramfs por el de la partición raiz.
- Otra opcion, mas empleada en sistemas embedded con sistemas de ficheros muy pequeños, es que el initramfs se convierta en la partición raiz del kernel y el su interior se aloje la aplicación del user-space que va a correr el sistema embedded.

La imagen initramfs

Introducido en el kernel 2.6 para conseguir un proceso de inicialización del kernel mucho mas limpio, ya que parte del código de inicialización del kernel se mueve al user-space. Solo esta soportado en kernels >= 2.6.17 configurados adecuadamente.

Como ya hemos visto, puede usarse en sistemas embedded como sistema de ficheros root del kernel, y en sistemas mas grandes, como sistema de ficheros intermedio para montar la partición raiz.

Para construir una imagen initramfs para el boot-loader brug, se hace esto:
$ mkinitramfs -o /boot/initrd.img-2.6.22.5-custom 2.6.22.5-custom

Para crear una imagen initramfs custom (casi nadie hace esto):
$ find  -print -depth | cpio -ov | gzip  -c  > initramfs.img

Para extraer el contenido de una imagen initramfs una vez generada:
$ gzip -dc initramfs.img | cpio -id



Etapa 4. El user-space

No vamos a entrar en muchos detalles, ya que el arranque del user-space es dependiente de cada distribución de Linux. Para no extendernos demasiado, explicaremos aqui el modelo genérico de linux, asumiendo que init=/sbin/init. Por tanto, el primer programa del user-space que tomará el control será /sbin/init, quien leerá el script /etc/inittab y lo ejecuta en secuencia.

Cada linea del fichero /etc/inittab tiene este formato:
id:runlevels:action:process

- id - Secuencia de 4 caracteres. Nosotros lo vamos a ignorar
- runlevels - Niveles de ejecucion. Nosotros lo vamos a ignorar
- action - Accion llevada a cabo cuando se ejecute la entrada
--> sysinit: proceso ejecutado durante el boot del sistema
--> restart: proceso se reinicia cuando termina
--> shutdown: proceso ejecutado con el shutdown del sistema
- process - Especifica linea de comandos del proceso ejecutado

Un ejemplo de fichero /etc/inittab típico de cualquier sistema Linux:
# Script de inicializacion del arranque del sistema
::sysinit:/etc/init.d/rcS
# El proceso /sbin/init se reinicia cada vez que termina
::restart:/sbin/init
# Proceso ejecutado cuando hacemos un shutdown
::shutdown:/bin/umount -a -r

Como vemos, la inicialización del user-space la completa el script apuntado por sysinit en inittab (/etc/init.d/rcS). Desde este script se configuran los dispositivos de red (ifconfig), se montan los virtual filesystems (/proc, /sys), se montan las particiones de datos (recordemos que la partición root ya esta montada), se inicializan los distintos servicios del sistema (http, smtp, ...).

Finalmente se muestra en pantalla el interfaz de usuario gráfico donde el sistema solicita usuario/password para iniciar la sesion.

miércoles, 2 de septiembre de 2009

Crónica de un urban runner

Hace años que practico mi afición de salir a correr por las calles de la ciudad en la que resido. Recorriendo la ciudad de esta forma uno aprende el callejero, se mantiene en forma y se relaja del stress de vivir en una gran ciudad. Como veis, el urban runner tiene muchos alicientes para practicar su deporte favorito.


Pero que nadie se olvide: ninguna practica deportiva esta exenta de riesgos. El urban runner esta continuamente expuesto al peligro de los atropellos. Obviamente, al de los coches y las motos cuando cruza la calle. Si. Pero tambien a los atropellos producidos por otros peatones cuando el urban runner transita por parques, aceras, paseos, calles... todos los sitios teóricamente "habilitados" para su práctica deportiva. Estos peatones "suicidas" presentan características muy peculiares que quiero compartir con vosotros:

- Jovencitas locas que ven a lo lejos su tienda favorita y dan un aceleron, enfilando en linea recta la entrada por su puerta principal, sin importarles lo mas minimo quien se cruce en su camino.
- Madres que se aproximan de cara con el carrito de su bebe haciendo "eses" hacia el mismo lado en el que tu intentas esquivarlas, hasta que finalmente te toca hacer una gran curva para evitarlas.
- Niños de 4 o 5 años que van cogidos de la mano de sus papis y que cuando estas a punto de adelantarles, sueltan de la mano al niño que empieza a purular por el unico espacio libre por donde podías pasar.
- Señoras mayores que van con su gayatito haciendo zig zag en la misma direccion en la que tu intentas esquivarlas, mientras te preguntas por qué no siguen una linea recta.
- Jovencitas locas que salen corriendo de su tienda de ropa favorita con dos bolsas en cada mano mientras por su cabeza solo ronda la idea de entrar en su otra tienda de ropa favorita, y se lanzan a cruzar la calle sin reparar quien se aproxima por su lado.
- Señoras mayores que ven una moneda de 2 centimos brillando en el suelo y que a pesar de que te han visto venir, deciden recogerla justo cuando estas a punto de pasar por ese mismo punto, agachandose al suelo cortandote la trayectoria.
- El típico chulito "killo", que se encara hacia ti mientras te aproximas a el y a pesar de ir cambiando poco a poco tu trayectoria para evitar colisionar, insiste en invadir tu trayectoria recta hasta que consigue desviarte completamente.
- Chiquillas adolescentes de 15 años con acné en la cara que se quedan mirandote mientras te acercas a ellas con cara de que les duele una muela, directas hacia la colisión te apartes hacia el lado que te apartes.
- Grupito de señoras mayores, muy animadas, que justo terminan la conversacion cuando estas proximo a pasar por su lado y se dispersan en todas direcciones sin preocuparse mas que por seguir despidiendose de sus amigas una y otra vez a voces.
- Divorciada maquillada y muy perfumada que tras tomarse su cafecito en el bar y pagar en la barra, sale a la calle despreocupada guardando el monedero en su bolso mientras cruza la calle sin percatarse que has estado a punto de atropellarla.
- Personas paseando su perro con 6 metros de correa extensible cortando el paso de extremo a extremo de la calle.
- Parejita romántica de las que andan cogiditos de la mano, a la que te acercas por su espalda e intentas adelantar por el trozo de acera que dejan libre y cuando estas a punto de hacerlo empiezan a separarse sin soltarse las manos cortardote inconscientemente el paso.
- Señoras mayores subiditas de peso que una vez hacen la intencion de bajar un bordillo no pueden detener esa intención ni aunque se queden mirandote mientras te acercas a ellas, con lo que finalmente se cruzan involuntariamente por donde tu querías pasar.
- Conductores que aparcan el coche a su izquierda y salen del coche, abriendo brúscamente la puerta, sin antes comprobar si alguien se acercaba por la acera.
- Jovencitas locas que salen corriendo de su otra tienda de ropa favorita con 4 bolsas en cada mano y mientras por su cabeza ronda el remordimiento de que su tarjeta de crédito está echando chispas, se lanzan a cruzar la calle sin reparar que vienes corriendo.

Esta es la lista de los atropellos mas curisosos que me han ocurrido en los últimos meses. Que nadie se preocupe: por el momento he salido ileso en todos ellos. Seguiré actualizando este post mientras la gravedad de los atropellos así me lo permita :-)

sábado, 22 de agosto de 2009

Qt4, QComboBox y el foco del teclado

Esta vez vamos a escribir un post que será útil para desarrolladores de la libreria Qt (version 4) que tengan interes en profundizar en la gestión del foco de teclado del widget QComboBox. Vamos a modificar el comportamiento standard de este widget, y supongo que por ese motivo la documentación de la libreria es poco clara en este sentido. Por ello creo que este post os puede servir para entender mejor este asunto.


La idea es implementar un widget custom haciendo uso de dos de los widgets predefinidos por la libreria: QLabel y QComboBox. Nuestra widget custom (ComboLabel) compondrá el QLabel y el QComboBox en un solo widget, de forma que cuando reciba el foco del teclado, desplegará automáticamente la lista del QComboBox, y cuando pierda el foco, la esconderá automaticamente. Vamos a usar la tecla "Enter" (Qt::Key_Enter) para hacer la transición del foco.

Este problema no plantea complicaciones en entornos donde existe un raton o una pantalla tactil, ya que en estos casos, el puntero aisla de los problemas de foco. Sin embargo, en los sistemas donde el único dispositivo de entrada es un teclado, la gestion del foco se convierte en uno de los problemas clave a gestionar y resolver por el desarrollador. Bueno, en uno mas :-)

Os planteo una primera propuesta para resolver el problema que en principio debe parecer obvia (aunque veremos que no funciona). Primero crear una subclase de QWidget (ComboLabel) que componga una instancia de la clase QLabel y de QComboBox en un mismo layout. Despues reimplementar los filtros de entrada (focusInEvent) y salida (focusOutEvent) del foco, para mostrar y ocultar automáticamente la lista. Por ultimo reimplementar el filtro de eventos de teclado (keyPressEvent) para hacer la transicion del foco cuando el usuario pulse la tecla Qt::Key_Enter.

ComboLabel::ComboLabel(QString title, QWidget *parent) : QWidget(parent)
{
setFocusPolicy(Qt::StrongFocus);

m_label = new QLabel(title);
m_combo = new QComboBox;

QHBoxLayout * mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_label);
mainLayout->addWidget(m_combo);
setLayout(mainLayout);
}

void ComboLabel::focusInEvent(QFocusEvent * event)
{
m_combo->showPopup();
}

void ComboLabel::focusOutEvent(QFocusEvent * event)
{
m_combo->hidePopup();
}

void ComboLabel::keyPressEvent(QKeyEvent * event)
{
switch(event->key()) {
case Qt::Key_Enter:
focusNextChild();
break;
default:
QWidget::keyPressEvent(event);
}
}

Esta propuesta parece obvia pero no funciona como queremos. El problema viene dado por la implementación del QComboBox, ya que este widget esta compuesto internamente por dos widgets, un QLineEdit y un QAbstractItemView, y cuando el QAbstractItemView del QComboBox toma el foco del teclado, nunca mas lo devuelve al padre. ¿Como resolvemos entonces este asunto?

La solución del problema (bastante tricky como vereis) consiste en crear una clase ComboBox (derivada de QComboBox), e instalar un filtro de eventos (installEventFilter()) en la vista desplegada (view()). Con este filtro se detectan los eventos de pulsacion de tecla sobre el QAbstractItemView, y se hace la transicion del foco cuando el usuario pulsa sobre dicha vista la tecla Qt::Key_Enter. Para terminar, cuando el widget recibe el foco debe desplegar la vista (showPopup()) y cuando abandona el foco, debe esconderla (hidePopup()). Ambos métodos deben ser reimplementados tal y como veremos, ya que la implementación de la clase padre (QComboBox) no es suficiente para nuestro objetivo.


Veamos los detalles:

ComboLabel::ComboLabel(QString title, QWidget *parent) : QWidget(parent)
{
m_label = new QLabel(title);
m_combo = new ComboBox;

QHBoxLayout * mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_label);
mainLayout->addWidget(m_combo);
setLayout(mainLayout);

setFocusProxy(m_combo);
}

ComboBox::ComboBox(QWidget * parent) : QComboBox(parent)
{
view()->installEventFilter(this);
}

bool ComboBox::eventFilter(QObject * obj, QEvent * event)
{
if (obj == view() && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast(event);
switch (keyEvent->key()) {
case Qt::Key_Enter:
hidePopup();
focusNextChild();
return QComboBox::eventFilter(obj, event);
}
}
return QObject::eventFilter(obj, event);
}

void ComboBox::showPopup()
{
if (!(view()->isVisible())) {
setRootModelIndex(QModelIndex());
QComboBox::showPopup();
}
}

void ComboBox::hidePopup()
{
if (view()->isVisible()) {
setRootModelIndex(view()->currentIndex().parent());
setCurrentIndex(view()->currentIndex().row());
QComboBox::hidePopup();
}
}

void ComboBox::focusInEvent(QFocusEvent * event)
{
if (count() > 0) showPopup(); else focusNextChild();
}

Para que podais probar el ejemplo en vuestro ordenador y analizarlo con mas calma, os dejo este tarball aqui. Insistid porque parece que el servidor web también esta de vacaciones :-). En él encontrareis todos los fuentes listos para ser compilados.

Espero que este pequeño ejemplo os sirva en el futuro para resolver mejor vuestros problemas de foco con QComboBox'es y toda clase de widgets custom que implementeis de ahora en adelante. La librería Qt4 es una librería muy extensa, asi que si alguien tiene interés en tratar algun tema en particular, podeis mandarme un correo sin ningun compromiso e intentaré hacer lo que pueda para ayudaros.

Por cierto... ¿que tal lo habeis pasado estas vacaciones? Las mías cortitas, este verano se han terminado pronto. Y terminadas las vacaciones, como veis, volvemos con energias renovadas y mas ganas de transmitir nuevos conocimientos a los lectores de este blog. Estamos en epoca de crisis, pero ilusion que no falte, que mientras nadie diga lo contrario... ¡sigue siendo gratis! :-)

sábado, 1 de agosto de 2009

Organizar un proyecto en C con librerias

Los programadores newbies en Linux podeis aprovechar este post para aprender a compilar y a usar vuestras librerías en C. Encontrareis muchos manuales en Internet mucho mas extensos y elaborados que este, pero yo lo que quiero transmitiros son conocimientos de forma rapida, para que lo pilleis a la primera sin necesidad de que perdais mucho tiempo. Así que, sin anestesia, nos ponemos manos a la obra:



Información de background

Segun programamos, encontramos funciones que se usan en muchas partes de nuestro codigo. Nos interesa tenerlas en un directorio separado, compiladas y listas para poder usarlas siempre que queramos. Las ventajas de esto son enormes:
- Evitamos los continuos copy/paste (código mas compacto)
- Reducimos tiempo de compilacion (solo se compilan una vez)
- Aumentamos fiabilidad con el tiempo de uso (mas probadas, menos bugs)

La librería estara compuesta por uno o mas ficheros .c fuentes y uno o mas ficheros .h de cabeceras. Veamos un ejemplo:
$ cat milib.h
#ifndef _MI_LIB_H
#define _MI_LIB_H
int suma(int a, int b);
int resta(int a, int b);
#endif

$ cat milib.c
int suma(int a, int b) { return a+b; }
int resta(int a, int b) { return a-b; }


Librerías estáticas vs librerías dinámicas

En linux podemos hacer dos tipos de librerías:
- Librerias estáticas
- Librerias dinámicas

Las librerías estaticas se añaden a la imagen de nuestro ejecutable. Una vez hecha esta operación, la librería puede borrarse y el código sigue funcionando, ya que nuestro binario resultante contiene todo lo que necesita de la librería.

Las librerías dinámicas no se añaden a la imagen de nuestro ejecutable. El ejecutable debe buscar la librería siempre que la necesite, y por tanto, la librería dinámica no puede borrarse, o nuestro programa dejaría de funcionar.

La elección del tipo de librería que debeis usar depende de la naturaleza del proyecto desarrollado. Es una eleccion en la que debeis valorar ventajas e inconvenientes, y llegar a un compromiso entre ambas:
- Ejecutable estatico ocupa mas espacio
- Ejecutable estatico es mas facil de instalar en otro PC
- Ejecutable estatico es mas rapido
- Ejecutable dinamico aprovecha mejoras de la librería compatible con el código del programa
- Ejecutable dinamico requiere refactorización con cambios incompatibles

En Linux (en general Unix) las librerías estáticas se nombran con la extension .a (libmia.a) y las librerías dinámicas se nombran con la extension .so (libmia.so).

Receta para construir y usar una librería estática

Partimos de nuestro programa miprograma.c y de los fuentes de nuestra libreria milib.c.
$ cat miprograma.c
#include
int main(void) {
printf("%d\n", suma(10,10));
printf("%d\n", resta(10,10));
}


Veamos los pasos necesarios para construir y hacer uso de una librería estática:
- Obtener los ficheros objeto .o de todos los fuentes .c de nuestra libreria
$ gcc -c milib.c -o milib.o

- Crear la libreria .a
$ ar -rv libmia.a milib.o

- Compilar nuestro programa, linkando con la libreria estatica
$ gcc -o miprograma miprograma.c -I. -L. -Bstatic -lmia

Observar que -Bstatic -lmia indica que se debe coger la libreria libmia.a. El prefijo lib y la extension .a ya las pone automaticamente el compilador gcc. La opción -Bstatic afecta a todas las librerías que van detrán en la línea de compilación.

Receta para compilar y usar una librería dinámica

Partimos de nuestro programa miprograma.c y de los fuentes de nuestra libreria milib.c. Veamos los pasos necesarios para construir y hacer uso de una librería dinámica:
- Obtener los ficheros objeto .o de todos los fuentes .c de nuestra libreria
$ gcc -c milib.c -o milib.o

- Crear la libreria .so
$ ld -o libmia.so milib.o -shared

- Compilar nuestro programa, linkando con la libreria dinámica
$ gcc -o miprograma miprograma.c -I. -L. -Bdynamic -lmia

Observar que -Bdynamic -lmia indica que se debe coger la libreria libmia.so El prefijo lib y la extension .so ya las pone automaticamente el compilador gcc. La opción -Bdynamic afecta a todas las librerías que van detrán en la línea de compilación.

El comando ldd sirve para ver las librerias dinamicas con las que se ha linkado un programa. Por ejemplo:
$ ldd miprograma
linux-gate.so.1 => (0xbfffe000)
libmia.so => not found
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e6f000)
/lib/ld-linux.so.2 (0xb7faa000)

Como vemos en el ejemplo, el programa no encuentra la libreria libmia.so. Hay que decirle al programa donde estan las librerías dinámicas. Para ello definimos la variable de entorno LD_LIBRARY_PATH de esta manera:
$ export LD_LIBRARY_PATH=/path/a/miprograma
$ ldd miprograma
linux-gate.so.1 => (0xbfffe000)
libmia.so => /path/a/miprograma/libmia.so (0xb7f2f000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7df7000)
/lib/ld-linux.so.2 (0xb7f34000)


Cierre del post

Es hora de que practiqueis vosotros, os tomeis un tiempo para probar este ejemplo y asimilar los conceptos, y empeceis a aplicar estos conocimientos en vuestros futuros proyectos.

Yo me despido del blog hasta despues del verano. Hoy cumplo 33 años y quiero aprovechar la ocasión para dedicarle este post a todos mis lectores, y en especial a aquellos que se acuerden de felicitarme. Os agradezco a todos las felicitaciones, pero yo lo que quiero son regalos little bit frikies! ;-) Que paseis un buen verano y nos leemos en Septiembre! :-)

viernes, 10 de julio de 2009

Estiramientos para calentar y enfriar

Me gustaría dedicar este post a todos los deportistas newbies, que por el motivo que sea deciden cambiar sus habitos de vida sedentarios por otros mas saludables. Esa energia que os animó en su momento a dar el primer paso puede aportaros mucha satisfacción a lo largo de vuestras vidas, pero debeis encauzarla adecuadamente para que no se os acabe pronto la mecha.

Y es que mucha gente abandona en pocas semanas la practica de deporte por falta de motivación, o peor aún, por alguna lesión producida por alguna sobrecarga durante sus primeras semanas de entrenamiento.

No podemos luchar contra la falta de motivación. Es un tema muy personal que depende de los gustos y la capacidad de sacrificio de cada individuo. Pero si podemos dar algunos consejos para reducir la aparición de las temidas lesiones, y evitar así culparlas de un temprano abandono de la actividad fisica.

Antes de iniciar cualquier actividad deportiva, sea del tipo que sea, es necesario realizar un buen calentamiento. Y lo voy a recalcar para que quede bien claro: hay que hacerlo siempre. Se trata de poner en funcionamiento el aparato locomotor, lo que yo llamo "arranque de motores". Lo mismo debe repetirse despues de terminar la actividad física, pero a la inversa, es decir, realizar un buen enfriamiento, o "parada de motores". Es como si cogemos un coche y lo ponemos de 0 a 200Km/h sin hacerle el rodaje. Lo mismo si apagamos el contacto del motor cuando el coche va a 200Km/h. (Bueno, lo dejaré en 120Km/h que no quiero incitaros a sobrepasar los limites de velocidad legales). Como podeis imaginar, el motor sufrirá mucho y correreis el riesgo de griparlo. Nuestro cuerpo funciona como el motor de ese coche. Por tanto debemos tratarlo con el mismo cuidado.

Para la fase de calentamiento os recomiendo realizar un trote suave "borriquero" de 5 minutos y tal como lo termineis, realizar la siguiente tabla de estiramientos (desde la cabeza hasta los pies). Debe llevaros unos 10/12 minutos en total.

- 10rep mirar nuestro hombro izquierdo y despues mirar nuestro hombro derecho.
- 10rep apoyar la oreja sobre el hombro izquierdo y despues sobre el derecho
- 10rep mirar al techo y al suelo
- 10rep elevación hombros con los brazos pegados al cuerpo (hacia arriba)
- 10rep rotación hombros con los brazos pegados al cuerpo (rotación delantera)
- 10rep rotación hombros con los brazos pegados al cuerpo (rotación trasera)
- 10sec con mano izquierda, coger codo derecho y llevarlo al hombro izquierdo
- 10sec con mano derecha, coger codo izquierdo y llevarlo al hombro derecho
- 10sec codo derecho en la nuca estirando hacia la izq. con mano izquierda
- 10sec codo izquierdo en la nuca estirando hacia la der. con mano derecha
- 10sec mano der. por el cuello y izq. por debajo espalda, coger manos y hacer un 8
- 10sec mano izq. por el cuello y der. por debajo espalda, coger manos y hacer un 8
- 10sec mano der. a la cintura y mano izq. por encima de la cabeza, doblar cintura
- 10sec mano izq. a la cintura y mano der. por encima de la cabeza, doblar cintura
- 10sec separar piernas, dejar caer cintura, palmas tocan suelo
- 10sec separar piernas, dejar caer cintura a la izq. manos tocando tobillo izq.
- 10sec separar piernas, dejar caer cintura a la der. manos tocando tobillo der.
- 10sec separar piernas, dejar caer culo sobre tobillo der. y estirada pierna izquierda
- 10sec separar piernas, dejar caer culo sobre tobillo izq. y estirada pierna derecha
- 10sec mirando al frente, estirar pierna izq. hacia delante sin mover la pierna der.
- 10sec mirando al frente, estirar pierna der. hacia delante sin mover la pierna izq.
- 10sec fuerza para tumbar una pared, manteniendo recta pierna izq. sin doblar rodilla
- 10sec fuerza para tumbar una pared, manteniendo recta pierna der. sin doblar rodilla
- 10sec de pie, cruzar pie izq. sobre pie der. y tocar tobillos con las manos
- 10sec de pie, cruzar pie der. sobre pie izq. y tocar tobillos con las manos
- 10sec de pie, subir talon izq. sobre un bordillo y mantener flexionado
- 10sec de pie, subir talon der. sobre un bordillo y mantener flexionado
- 10rep de pie, rotacion tobillo izq. apagando colilla sentido horario
- 10rep de pie, rotacion tobillo izq. apagando colilla sentido antihorario
- 10rep de pie, rotacion tobillo der. apagando colilla sentido horario
- 10rep de pie, rotacion tobillo der. apagando colilla sentido antihorario
- 10rep de pie, flexionar rodillas, rotacion de ambas en sentido horario
- 10rep de pie, flexionar rodillas, rotacion de ambas en sentido antihorario


Para la fase de enfriamiento, nunca pareis de golpe y os senteis en un sofá, debeis andar durante 5 minutos mientras os bajan las pulsaciones. Despues os recomiendo realizar la siguiente tabla de estiramientos en la que todos los ejercicios se hacen en el suelo. En total son 6/8 minutos mas.

- 10sec juntar las plantas de los pies y tirar las rodillas al suelo
- 10sec pierna izq. estirada al frente y tocar punta del pie.
- 10sec pierna der. estirada al frente y tocar punta del pie.
- 10sec abrir piernas y estirar brazos intentando tocar el suelo con el pecho
- 10sec abrir piernas y estirar brazos y coger pie izq. con las dos manos
- 10sec abrir piernas y estirar brazos y coger pie der. con las dos manos
- 10sec acostado boca arriba, llevar rodilla izq. sobre el pecho
- 10sec acostado boca arriba, llevar rodilla der. sobre el pecho
- 10sec acostado boca arriba, llevar rodilla izq. y rodilla der. sobre el pecho
- 10sec acostado boca abajo, presionar talon del pie izq. sobre el culo
- 10sec acostado boca abajo, presionar talon del pie der. sobre el culo
- 10sec acostado boca abajo, presionar talones del pie izq. y der. sobre el culo

Estos ejercicios mejorarán la elasticidad de vuestros musculos. Con ello evitareis lesiones musculares, sobrecargas, contracturas, distensiones. Tambien son buenos como remedio contra las agujetas.

Si haceis bien estos ejercicios podreis practicar deporte por muchísimo tiempo sin tener prácticamente lesiones tontas, y os será mas dificil abandonar el deporte con la excusa de que a vosotros os ha tratado mal, que el deporte es malo para salud, o frases por el estilo que seguro habeis escuchado en mas de una ocasión. Vosotros disponeis de la información necesaria para hacer mejor las cosas y no abandonar a la primera. Es hora de ponerse manos a la obra, chicos. ¡A estirar se ha dicho!

sábado, 25 de abril de 2009

Operación bikini: howto

Llega el veranito y con su cercanía mucha gente empieza a plantearse lo de apuntarse a un gimnasio y ponerse a dieta para perder unos kilitos y lucir un bonito cuerpo en la playa.

No soy experto en la materia. INEF se convirtió en mi vocación frustrada cuando tome la decision de hacerme informático (que por otra parte se trata de mi vocación realizada ;-) De todas formas, creo que conozco lo suficiente del tema como para daros algunos trucos y consejos que seguro os serviran para mejorar vuestro aspecto fisico en general. Y es que son ya 21 años practicando distintos deportes, 7 de los cuales con entrenadores nacionales de baloncesto, y los 14 restantes aplicando por mi cuenta los conocimientos que de ellos aprendí cuando todavía era un adolescente.

Asi que sin mas vacilación, nos ponemos manos a la obra y entramos en materia. ¡Que tiemblen los kilos de mas!

Tres puntos basicos para alcanzar nuestro objetivo:
- Alimentación
- Hidratación
- Deporte

Punto básico 1: Alimentación

La alimentación es básica para mejorar nuestro aspecto físico (y nuestra salud). Se trata de aprender a comer bien, y tener la fuerza de voluntad suficiente para no pecar comiendo cosas que estan muy ricas pero que no le hacen ninguna falta a nuestro organismo. Ya os digo que no vais a pasar hambre, asi que tranquilos que nadie va a tener que preocuparse por eso.

De la alimentacion necesitamos entender tres cosas importantes:
- Reducir la ingestión de grasas
- Aumentar la ingestión de fibras
- Dosificar la ingestion de hidratos y proteinas.

Las grasas sirven de muy poco para nuestro organismo. Se acumulan rapidamente como reservas energeticas y pronto aparecen los malditos michelines. Por ello debemos prescindir por completo del consumo de bolleria (donuts, bollycaos, croissants, etc) y alimentos fritos (patatas fritas, carne frita, huevos fritos, etc.). Tambien hay que eliminar de la dieta los productos lácteos sin descremar y las yemas de huevo, ya que contienen una alta concentración de grasas saturadas y colesterol. Por tanto, cuando compremos yogures, queso o leche, debemos elegir productos desnatados.

No obstante, nuestro organismo necesita el aporte de una cantidad minima de grasas al dia que vamos a ingerir de las carnes blancas (pechugas de pollo y pavo) y del pescado. Tambien os recomiendo tomar una cucharada de aceite de oliva virgen crudo al dia, lo que ayuda a eliminar el colesterol malo de nuestro organismo. Por ultimo, está demostrado que la grasa vegetal de las nueces es muy eficaz para destruir el colesterol malo, asi que también vamos a incluirlas en nuestra dieta diaria.

La fibra nos permitira ir al baño con regularidad. Si queremos perder peso, ¿no es esto lo mas facil? :-) Para ello el truco son los copos de avena, eso si que os va a dar regularidad y no los danones Activia. Hace cosa de 2 años que descubri ésto y desde entonces soy un reloj de cucko :-) Y por supuesto, la verdura (ensaladas) y fruta.

Los hidratos de carbono (arroz, pasta y patata) son la gasolina de nuestro organismo: cuanta mas actividad física, mayores necesidades de hidratos tendreis. Las proteínas (carne de pollo y pavo, pescado y claras de huevo) son las que reconstruyen las fibras de vuestros musculos provocadas por el desgaste del día a día. Por dosificar la ingestión de hidratos y proteínas me refiero a que en funcion de la actividad física que tengais cada día, tendreis que aumentar/disminuir la cantidad que tomareis, aumentándola los dias que realiceis ejercicio fisico y disminuyendola el resto de los días. Lo importante es que consumais la energia suficiente para desenvolveros en vuestro día a día con normalidad, pero nunca mas de la necesaria.

Una vez tenemos claros los alimentos que nos convienen, vamos a ver como organizar las comidas del día. Existe la leyenda urbana que dice que haciendo solo 3 comidas al día podremos adelgazar mas que si comemos 4 o 5 veces... Yo no soy partidario de esa teoría y no os lo recomiendo en absoluto. Al hacer menos comidas al día, se tiende a llenar mas el estomago en cada comida para no pasar hambre hasta la siguiente comida, y eso hace que las paredes de vuestro estomago se agranden. Al tener mayor volumen en el estomago, podeis llenarlo con mas cantidad de alimentos, con lo cual va a provocar que cada vez que comais lo lleneis mas y mas, lo cual os llevará a tener un estomago todavia mas grande (...).

Yo os recomiendo hacer 5 comidas al dia, mas o menos una cada 3 horas, en cantidades que no os quedeis con hambre, pero tampoco os hincheis demasiado. Se trata de que entre las comidas no noteis sensación de estar hambrientos. El cuerpo siempre debe tener alimento suficiente para que podais desenvolveros con vuestras tareas cotidianas con normalidad.

Tambien es importante la hora del día a la que tomais cada alimento. Los hidratos de carbono (arroz, pasta, patata...) no los tomeis mas tarde de la comida de mediodia, ya que los quemareis durante la actividad fisica que hagais por la tarde. En cambio, si los tomais en la cena, antes de iros a dormir, vuestro organismo no los consumirá, y los acumulará como reservas energeticas que os haran engordar por la noche.

En concreto, yo os aconsejo estas 5 comidas (prohibido picar entre comidas).
- Desayuno (7/8h)
- Almuerzo (10/11h)
- Comida (13/15h)
- Merienda (17/18h)
- Cena (20/22h)

Para el desayuno, el bol de copos de avena con leche desnatada. Esto es lo basico para que vayais al baño con regularidad. Es increible, pero en 3 semanas estareis notando los resultados.

Para el almuerzo, un bocadillo de atun natural (que podeis acompañar con tomate natural o con unas aceitunas), de pechuga de pavo, o de tortilla francesa sin freir (como si hicierais una creppe).

Para la comida, de primer plato arroz, pasta o hervido. Y de segundo una pechuga de pollo o de pavo a la plancha, o bien una sepia a la plancha o un poco de pescado (sardina, emperador, lenguado). Y de postre una o dos piezas de fruta (kiwis, naranjas, manzanas, peras o piña).

Para la merienda, un platano, un yogourt 0% grasa, unas almendras o avellanas, unos cereales o unas galletas Maria, y podeis incluir un quesito burgo de arias 0% grasa con mermelada o membrillo.

Y para la cena, una crema de verduritas (yo compro cremas Knorr) con una cucharadita de aceite y unas cuantas nueces. O bien una ensalada con tomate, lechuga, pepino, cebolla, maiz, media manzana, dos esparragos, unas nueces y un huevo duro (prescindiendo de la yema). Y que podeis combinar con atun natural o con dos patitas de cangrejo congelado. Y de postre otra pieza de fruta.

Os pongo las fotos de una comida tipica de mi dieta de un dia cualquiera del año:







Como veis, hay variedad. Es una dieta sana, equilibrada y que os permitira perder grasa de vuestro cuerpo con facilidad. Al no ingerir mucha grasa, vuestro organismo ira quemando (poco a poco) las reservas de grasa que teneis acumuladas en las paredes de vuestros músculos, por tanto estareis consiguiendo vuestro objetivo de reducir volumen y perder peso de una forma sana.



Punto básico 2: Hidratación

Es otro de los aspectos básicos para que mejoreis vuestro aspecto fisico (y vuestra salud). El cuerpo humano esta formado en un 65/70% por agua, por tanto debemos depurar esa cantidad de liquido constantemente. Para ello se recomienda beber como mínimo 2l de agua al dia. Para controlar la cantidad consumida, os recomiendo comprar una botella de agua de 2l de plastico, y rellenarla cada dia, teniendo en cuenta que antes de iros a dormir debe estar vacia todos los días. El agua filtrará nuestro organismo, eliminando impurezas, toxinas y tejidos adiposos, asi que ya sabeis que cada vez que orineis estareis mejorando vuestro estado de salud, por tanto cuanto mas agua bebais, mejor.

Otro aspecto importante es cuando debeis beber ese agua. Yo os recomiendo que lo hagais entre comidas y eviteis beber agua durante las comidas. La razón es muy simple: si llenais el estomago de agua cuando estais comiendo, pronto sentireis que estais llenos y que no teneis mas hambre. Una hora mas tarde estareis con la tripa vacia (el agua no alimenta mucho) y desesperados por picar algo antes de la siguiente comida.

Los dias que practiqueis algun deporte, al terminar la actividad física debeis beberos un zumo de frutas o una bebida isotónica como el Isostar o el Aquarius para reponer las vitaminas y las sales minerales que hayais perdido de la sudoración durante el ejercicio.

Por ultimo, olvidaros de las bebidas con gases, como la CocaCola, la Fanta, gaseosa o derivados. Os hincharan mucho y no es eso lo que buscamos.

Punto básico 3: Deporte

Mucha gente piensa que con hacer un poco de deporte se puede adelgazar, y eso no es del todo cierto. El 70% del cuerpo de un deportista de élite esta basado en su dieta. Sin una correcta alimentación, el deportista nunca llegaría a tener ese cuerpo. Pero tambien es cierto que no solo se consigue comiendo bien. Por tanto, dieta y deporte se complementan uno al otro.

Ya hemos aprendido a comer y a beber bien. Nos queda por explicar que ejercicios debemos hacer para aprovechar la dieta sana que estamos haciendo y acelerar el metabolismo de nuestro cuerpo para que consuma mas energia de la que ingerimos comiendo.

Esta demostrado que practicar deporte 1 o 2 días a la semana sirve de poco. Imagina que durmieras solo dos días a la semana: el Viernes y el Sabado: el resto de la semana estarías muerto de sueño. Si dormimos todos los días y comemos todos los días, ¿no deberíamos hacer deporte todos los dias?

Los buenos resultados se consiguen practicando ejercicio al menos 3 días a la semana, aunque yo os recomiendo 5 días. Esta claro que necesitais acostumbrar el cuerpo a la carga de trabajo, asi que empezar haciendo 3 días a la semana e ir incrementando el ritmo muy poco a poco, sin ninguna prisa.

Yo planifico mis entrenamientos en 5 días a la semana, repartiendo todos los grupos musculares que entreno entre esos 5 días:

- Piernas (3 días por semana)
- Pecho (1 dia por semana)
- Triceps (1 dia por semana)
- Hombros (1 dia por semana)
- Biceps (1 dia por semana)
- Dorsales (1 dia por semana)
- Abdominales (4 días por semana)

En concreto, organizo mis entrenamientos de esta forma:

Primer día:
5 minutos estiramientos de activación
15 minutos carrera farlek (sprint ritmo 3.30 min/km + recuperacion ritmo 6 min/km)
3 ejercicios de pecho (serie de 3x12)
3 ejercicios de triceps (serie de 3x12)
200 abdominales en series de 20/30
5 minutos estiramientos de parada

Segundo día:
5 minutos estiramientos activación
15 minutos carrera continua (ritmo 5 min/km)
Ejercicios con pesas de los distintos grupos musculares de las piernas.
200 abdominales en series de 20/30
5 minutos estiramientos de parada

Tercer día:
5 minutos estiramientos activación
3 ejercicios de hombro (serie de 3x12)
3 ejercicios de biceps (serie de 3x12)
200 abdominales en series de 20/30
5 minutos estiramientos de parada

Cuarto día:
10 minutos carrera continua (ritmo 5.30 min/km)
5 minutos estiramientos activación
30 minutos de sprints pista atletismo
5 minutos estiramientos de parada

Quinto día:
5 minutos estiramientos activación
5 ejercicios de dorsales (serie de 3x12)
200 abdominales en series de 20/30
5 minutos estiramientos de parada

Si hay alguien muy interesado en conocer mas detalles de este entrenamiento, que se ponga en contacto conmigo y se los daré con mucho gusto. Y como no se puede predicar sin dar ejemplo, los que me conoceis ya sabreis que no me gusta presumir de mi cuerpo, pero si no os enseño una foto no vais a creer en los resultados, asi que ahi va esta instantánea para motivar al personal:



Con esfuerzo estais todos capacitados para conseguirlo. Si lo intentais, pronto obtendreis los primeros resultados. Y con los primeros resultados, la motivación necesaria para seguir adelante aumentará. Espero que me comenteis los resultados si poneis este plan de dieta/entrenamiento en práctica. Tambien agradecería que gente con mas conocimientos en esta materia me corrija si hay algo que pudiera mejorarse. ¡Animo gente! ¡Como vamos a presumir este verano de cuerpo bonito!

sábado, 21 de marzo de 2009

El targetfs de un sistema embedded

Un sistema embedded es un sistema informático de bajo coste, y de propósito general, que corre sobre una plataforma hardware con recursos generalmente escasos. El hecho de que los recursos hardware escaseen en el sistema embedded, plantea problemas nuevos al ingeniero de software generalmente acostumbrado a trabajar con un ordenador de sobremesa. Imagina por un momento que tuvieras que instalar una distribución de Linux de las tipicas (Ubuntu, Fedora, Suse, etc.) en un disco duro de solo 4MB. Una distribucion Debian tipica minima (excluyendo el kernel) ocupa unos 40MB, demasiado para nuestro sistema embedded. Necesitas una alternativa bastante mas ligera.

El objetivo de este post es generar un targetfs para el sistema embedded que tenga disponibles todas las aplicaciones del user-space necesarias para manejar tu dispositivo embedded (target). Para ello usaremos la herramienta busybox.



Su manual (man) lo define como "The Swiss Army Knife of Embedded Linux", algo asi como "la navaja suiza de los Linux embedded". Busybox es un único binario que combina pequeñas versiones de los distintos comandos basicos de un sistema Linux. En terminologia busybox, cada comando basico es un "applet". La lista de los 107 applets incluidos no tiene desperdicio:

addgroup, adduser, adjtimex, ar, arping, ash, awk, basename, bunzip2,
busybox, bzcat, cal, cat, chgrp, chmod, chown, chroot, chvt, clear, cmp,
cp, cpio, crond, crontab, cut, date, dc, dd, deallocvt, delgroup, deluser,
devfsd, df, dirname, dmesg, dos2unix, dpkg, dpkg-deb, du, dumpkmap,
dumpleases, echo, egrep, env, expr, false, fbset, fdflush, fdformat, fdisk,
fgrep, find, fold, free, freeramdisk, fsck.minix, ftpget, ftpput, getopt,
getty, grep, gunzip, gzip, halt, hdparm, head, hexdump, hostid, hostname,
httpd, hush, hwclock, id, ifconfig, ifdown, ifup, inetd, init, insmod,
install, ip, ipaddr, ipcalc, iplink, iproute, iptunnel, kill, killall,
klogd, lash, last, length, linuxrc, ln, loadfont, loadkmap, logger, login,
logname, logread, losetup, ls, lsmod, makedevs, md5sum, mesg, mkdir,
mkfifo, mkfs.minix, mknod, mkswap, mktemp, modprobe, more, mount, msh, mt,
mv, nameif, nc, netstat, nslookup, od, openvt, passwd, patch, pidof, ping,
ping6, pipe_progress, pivot_root, poweroff, printf, ps, pwd, rdate,
readlink, realpath, reboot, renice, reset, rm, rmdir, rmmod, route, rpm,
rpm2cpio, run-parts, rx, sed, seq, setkeycodes, sha1sum, sleep, sort,
start-stop-daemon, strings, stty, su, sulogin, swapoff, swapon, sync,
sysctl, syslogd, tail, tar, tee, telnet, telnetd, test, tftp, time, top,
touch, tr, traceroute, true, tty, udhcpc, udhcpd, umount, uname,
uncompress, uniq, unix2dos, unzip, uptime, usleep, uudecode, uuencode,
vconfig, vi, vlock, watch, watchdog, wc, wget, which, who, whoami, xargs,
yes, zcat

Busybox funciona usando argv[0] para determinar el applet que debe invocar. Al renombrar el binario de busybox con el nombre de un applet determinado, se ejecuta dicho applet. Sin embargo esto no es practico. El truco que usa busybox es tener un único binario llamado "busybox" y tener un enlace (link) simbólico distinto por cada applet apuntando al binario de busybox. Asi por ejemplo:
$ ls -l /bin
-rwxr-xr-x 1 0 0 272800 busybox
lrwxrwxrwx 1 0 0 12 sh -> busybox
lrwxrwxrwx 1 0 0 12 cp -> busybox
lrwxrwxrwx 1 0 0 12 ls -> busybox

Para crear los enlaces simbólicos, se usa el comando ln:
$ ln -fs busybox sh
$ ln -fs busybox cp
$ ln -fs busybox ls

Así por ejemplo, para ejecutar un listado largo usando el applet ls, hacemos:
$ /bin/ls -l

donde /bin/ls es en realidad un link apuntando al binario busybox.

Para compilar busybox, hay que descargar los fuentes, preferiblemente del sitio oficial http://www.busybox.net/downloads/. Para obtener los fuentes de la versión 1.9.0 y extraer su contenido, hacemos esto:
$ cd /usr/src
$ wget http://www.busybox.net/downloads/busybox-1.9.0.tar.gz
$ tar xvfz busybox-1.9.0.tar.gz

Durante el proceso de configuración de la compilación de busybox, el usuario decide los applets que integra el binario resultante una vez compilado. Para ello, busybox emplea un método similar al de la compilación del kernel de Linux (.config), pudiendo usar varias opciones:
$ make allnoconfig
$ make oldconfig
$ make menuconfig

Para realizar la compilación, basta con ejecutar el comando make, igual que se hace con el kernel de Linux, y el binario resultante aparece en la raiz de los fuentes:
$ make

Despues de un buen rato esperando, tendras compilado tu busybox.

Retomando el objetivo inicial de este post, nos interesa generar un targetfs para el dispositivo embedded. Para ello crea una partición de 4MB en un fichero de tu disco duro (por ejemplo targetfs4M.img) y crear un sistema de ficheros en su interior (por ejemplo, formatealo con EXT2).
$ dd if=/dev/zero of=targetfs4M.img bs=1M count=8
$ mkfs.ext2 -F targetfs4M.img

Despues monta la partición de 4MB recien creada (targetfs4M.img) en el sistema de ficheros de tu ordenador de sobremesa, por ejemplo en el directorio /media/removable.
$ mount -o loop targetfs4M.img /media/removable

Por ultimo instala el binario de busybox en el targetfs de tu sistema embedded:
$ make install CONFIG_PREFIX=/media/removable

La instalación copia el binario del busybox en /media/removable (en la partición de 4MB montada en ese directorio) y crea en su interior todos los enlaces simbólicos a los applets configurados y compilados dentro del directorio de compilación.

Con esto ya tienes un targetfs básico para tu sistema embedded. No estará completo porque deberás añadir la aplicación que deba correr tu sistema embedded, pero ya dispones de un buen punto de partida para empezar a jugar con tu sistema. Ah! Y no olvides hacer un sync y desmontar /media/removable antes de hacer nada mas con esa partición!

viernes, 27 de febrero de 2009

Ya no me gustas GNOME: bienvenido XFCE

He sido usuario de GNOME durante los últimos 5 años. No tenía nada en contra de KDE (de hecho desarrollo habitualmente con la libreria Qt), pero una vez me acostumbré a sus atajos de teclado, llegó el momento que sin ellos mi vida ya no tenia sentido. ¡Que sería de mi si no pudiera abrir un nuevo tag del terminal con Mays+Ctrl+t [...]!

GNOME y KDE son dos de los escritorios de Linux mas extendidos en la actualidad. Los dos cumplen su función de manera extraordinaria, facilitando las tareas a los usuarios, sobre todo a aquellos usuarios que yo llamo "de la generación ventana", poco o nada acostumbrados al uso del terminal. (A todos vosotros, no sabeis lo que os perdeis. Bueno, este será tema de otro debate).

Sin embargo, ambos escritorios comparten un serio problema que me disgusta bastante, acentuado sobre todo en sus últimas versiones: un consumo de recursos exagerado, que causa una caida notable del rendimiento del PC. Esta perdida de rendimiento se nota mucho mas en los PCs con menos cantidad de memoria RAM. ¿No era ese uno de los motivos por los que yo no gustaba de usar Windows [...]?

En el caso de GNOME corriendo en mi PC con 1GB de memoria RAM, mas de 500MB los consumía GNOME, el solito. Y claro, cuando los recursos de tu PC escasean y la economía no está para muchos extras tecnológicos (esperaremos tiempos mejores), uno tiene que mirar alternativas que satisfagan sus necesidades de la mejor manera posible.

Y buscando por google encontré una alternativa que me gustó, y me gustó mucho. Tanto que desde entonces ha pasado a ser el nuevo escritorio de mi PC. Se trata del escritorio XFCE (version 4) que viene de serie en la distribución XUbuntu.

Como podeis ver en este pantallazo, a primera vista se trata de un escritorio similar a cualquier otro que ya esteis acostumbrados a usar:



Si seguis mirando capturas de pantalla vereis que pese a su sencillez, es bastante completo: un panel con multitud de opciones para su configuración, escritorios virtuales, transparencias en las ventanas, en los marcos, applets para la barra de tareas. Y por lo que he podido probar hasta ahora, muy estable.







Estamos de acuerdo en que no es un GNOME+compiz con escritorios virtuales rotando en 3D con efectos de aguas al mover la ventanas, iconos animados y tal. Pero, ¿y que me aporta a mi toda esa parafernalia? Pues en realidad muy poco. Esas características las usamos mas para presumir de escritorio bonito que para aumentar nuestra productividad.

En cambio, ¿que gano yo usando XFCE? Un escritorio que consume 14MBytes en memoria RAM, y deja libre casi 1GByte de memoria RAM para que se ejecuten las aplicaciones de mi PC. Desde que lo he instalado, mis aplicaciones estan radiantes de felicidad, dando saltos de alegría por los bits de mi memoria RAM. Todas han abandonado el cuarto oscuro llamado "la partición de swap" por completo. Y me lo agradecen todos los días dandome unos tiempos de respuesta inauditos desde hacía mucho tiempo. Y ese placer espiritual que produce poder abrir un nuevo tag del xfce4-terminal con Mays+Ctrl+t [...]

¿Que mas se le puede pedir a un escritorio? Sin duda alguna... ¡Me gustas XFCE, bienvenido a mi PC!

sábado, 31 de enero de 2009

Usando valgrind + memcheck como debugger

Linus Torvalds declaró en este post su postura contraria al uso de debuggers en el kernel, argumentando que son herramientas usadas por los malos desarrolladores que, lejos de aprender de sus errores, se concentran en resolver el problema sin profundizar en la causa real del error. Y por tanto, prefiere mantenerlos lejos del desarrollo del kernel. Desde luego que tiene mucha razón (palabra de Linus).

Mi postura, no tan radical, aunque totalmente de acuerdo con sus argumentos. Es deseable desarrollar con sumo cuidado e intentar evitar todos los fallos durante la codificación, pues detectarlos a posteriori en ocasiones puede ser complicado. Sin embargo, puede que tengamos que analizar algun core de código que no hemos escrito nosotros. Y en una línea que nunca en la vida debería fallar. ¿Que esta ocurriendo?. ¿Que hacemos ahora? Es en estos casos cuando necesitamos ayuda de lo que yo llamo "las fuerzas especiales".


En este post os voy a explicar como usar el debugger valgrind con la herramienta memcheck para detectar 5 errores comunes en la programación de C/C++. Lo vemos en estos 5 test:

Test 1: Detección de una perdida de memoria:

03 int main()
04 {
05 char *x = malloc(100); /* memory leak */
06 return 0;
07 }
$ gcc -g test1.c -o test1
$ valgrind --tool=memcheck --leak-check=yes ./test1
==8458== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8458== at 0x4C265AE: malloc (vg_replace_malloc.c:207)
==8458== by 0x40051D: main (test1.c:5)


Test 2: Detectar escrituras fuera de los limites de la memoria reservada:

03 int main()
04 {
05 char *x = malloc(10);
06 x[10] = 'a'; /* write out of bounds */
07 return 0;
08 }
$ gcc -g test2.c -o test2
$ valgrind --tool=memcheck --leak-check=yes ./test2
==17039== Invalid write of size 1
==17039== at 0x40052A: main (test2.c:6)
==17039== Address 0x519d03a is 0 bytes after a block of size 10 alloc'd
==17039== at 0x4C265AE: malloc (vg_replace_malloc.c:207)
==17039== by 0x40051D: main (test2.c:5)


Test 3: Detectar el uso de variables sin inicializar:

03 int main()
04 {
05 int x;
06 if (x == 0) /* uninitialised variable */
07 printf("x is zero");
08 return 0;
09 }
$ gcc -g test3.c -o test3
$ valgrind --tool=memcheck --leak-check=yes ./test3
==17070== Conditional jump or move depends on uninitialised value(s)
==17070== at 0x400518: main (test3.c:6)


Test 4: Intentar liberar una zona de memoria que no ha sido reservada:

03 int main(void)
04 {
05 char * str;
06 free(str); /* free not allocated */
07 return 0;
08 }
$ gcc -g test4.c -o test4
$ valgrind --tool=memcheck --leak-check=yes ./test4
==17092== Conditional jump or move depends on uninitialised value(s)
==17092== at 0x4C25265: free (vg_replace_malloc.c:323)
==17092== by 0x40051C: main (test4.c:6)


Test 5: delete en C++ mal hecho:

01 int main(void)
02 {
03 char * str = new char[10];
04 delete str; // instead of: delete [] v;
05 return 0;
06 }
$ g++ -g test5.c -o test5
$ valgrind --tool=memcheck --leak-check=yes ./test5
==17116== Mismatched free() / delete / delete []
==17116== at 0x4C24DAD: operator delete(void*) (vg_replace_malloc.c:342)
==17116== by 0x40067A: main (test5.cpp:4)


Hemos visto que valgrind es una herramienta de mucha ayuda para un desarrollador de C/C++ que sin duda nos ayudará a resolver muchos bugs. No obstante, tambien tiene sus limitaciones, por ejemplo que memcheck no comprueba los limites en los arrays estaticos, y por tanto no detecta este error:

01 int main()
02 {
03 char x[10];
04 x[11] = 'a'; /* not detected! */
05 return 0;
06 }


No obstante, debemos recordar las palabras de Linus. Los debugger son para los malos programadores. Y nosotros queremos ser buenos programadores. Asi que debemos aprender de nuestros errores e intentar que no vuelvan a repetirse en el futuro. Si seguis estos consejos, los debuggers tienen los días contados :-) En todo caso, para mi, el mejor debugger que ha existido y que siempre existirá es el printf (en C) o el cout (en C++).

Visitas:

Seguidores