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!

Visitas:

Seguidores