sábado, julio 14, 2007

Compilación de módulos bajo Linux

Desde que entré en el mundo de Linux me ha llamado la atención el núcleo y todo lo que represente meter mano por ahí. Lo malo de eso es que resulta engorroso, confuso y complicado empezar (al menos a mi me pasa), después de ganar cierta experiencia moviendome en sistemas UNIX (o sea Linux para que nos vamos a engañar...) me he dado cuenta de que la parte más fructífera para el informatico de a pié son los módulos.

¿Qué es un módulo? Mucha gente cree que un módulo en Linux es un driver, un programa para manejar un cacharro. En principio yo también lo pensé, es más, surgieron precisamente para ese motivo, pero un módulo es más que eso. Un módulo se puede ver a grosso modo como un cacho más del núcleo, un pedazo de código que hace algo, puede ser manejar un dispositivo o puede ser ordenar un vector, que se yo, cualquier cosa. La característica más resaltable de los módulos como todos saben es la posibilidad de la carga y descarga de ese cacho de código mientras el núcleo está funcionando. Para desarrolladores hay otra característica igual de importante que es el hecho de que no hay que recompilar el núcleo para crear el módulo (gracias a dios!).

Lo que voy a poner a continuación después de esta comida de bola es algunas notitas para mi mismo y para quién las necesite sobre como compilar un módulo.
  1. Necesitamos los fuentes de un núcleo. OJO! si queremos que el módulo funcione para el núcleo que corre actualmente hacen falta los fuentes de ese núcleo obviamente, pero podemos generar módulos para otras versiones de núcleo diferentes a la que está corriendo... lógicamente no podremos cargarlos por la incompatibilidad de versiones (aunque creo que se puede desactivar cuando se compila el núcleo) así que lo normal es trabajar con un núcleo X.Y.Z corriendo y tener los fuentes del núcleo X.Y.Z para generar módulos para un núcleo X.Y.Z.
  2. Necesitaremos compilar el núcleo, esto es debido a que hace falta generar el árbol de dependencias para luego poder compilar módulos. Al compilarlo una vez ya se crea este árbol, no hace falta recompilar el núcleo cada vez que queremos compilar un módulo.
  3. Crear un makefile con una sintaxis especial, luego veremos ejemplos.
  4. Compilar el módulo, debe ser compilado dentro del contexto del árbol de dependencias del núcleo, así que no vale ejecutar make y ya está, luego veremos como se hace.
  5. Cargar el módulo con insmod o modprobe. El segundo es más inteligente que el primero, deberiamos acostumbrarnos a usarlo.
  6. Abrir una cervecita, beber y decir "joder! que de puta madre!" si todo funciona else decir "esto es una mierda, el puto ole no sabe explicarse!", abrir una cervecita, beber y descubrir que está pasando.
  7. Si todo funcionó empezar a usar el módulo para darte cuenta de que no funciona el programa en si y que tienes que buscar fallos. Documentación de debugging de módulos hay en el tema 4 del libro "Linux Device Drivers" de Jonathan Corbet, Alexandro Rubini y en la tercera edición también Greg Kroah-Hartman. MUY ENCARECIDAMENTE SE LOS RECOMIENDO EN INGLÉS Y NO EN ESPAÑOL! He mirado la segunda edición en inglés y la tercera en español... no hay color, la traducción es muy mala. Desde aquí se lo dedico Pedro J. Gómez Corriente.
Ejemplitos de código estúpido y compilación sarna (el típico, hola mundo):

---------------------------------------------------------------------------------------
#define EL_MUNDO_APESTA 0

int algo()
{
printk(KERN_ALERT "HOLA MUNDO!!!\n"); //OJO al \n que muchas recompilaciones se hacen por ellos
return EL_MUNDO_APESTA;
}

int blablabla()
{
printk(KERN_WARNING "descargando modulo\n");
return 0;
}

module_init(blablabla);
module_exit(algo);
---------------------------------------------------------------------------------------

El ejemplo lo he picado con la misma sin mirar nada así que es altamente probable que no funcione. Seguramente faltarán bibliotecas, creo que para el tema de módulos hay que añadir siempre una tal linux/modules.h pero no sé. Cuando el make pete miran lo que dice resuelven y tan amiiiiiigos noooooo?!

Makefile para un módulo que es generado por UN ÚNICO fichero objeto.
-----------------------------------------------------------------------------------------
obj-m := nombre_que_queremos_para_el_modulo.o
-----------------------------------------------------------------------------------------

Makefile para un módulo que es generado por VARIOS ficheros objeto.
-----------------------------------------------------------------------------------------
obj-m := nombre_que_queremos_para_el_modulo.o
module-objs := fichero1.o fichero2.o .....
-----------------------------------------------------------------------------------------

Orden make para compilar:

make -C directorio_de_los_fuentes_del_núcleo M=direccion_donde_quiero_estar_despues_de_compilar modules

No hay comentarios: