martes, 1 de diciembre de 2009

Como compilar un módulo del kernel

La primera pregunta al leer el título de post será ¿Para qué quiero compilar un módulo del kernel?. Pues bien, si trabajas habitualmente con linux y con hardware variado llegará el día en que los drivers suministrados por el fabricante para dicho hardware no se corresponderán con el kernel que tienes en la máquina donde has instalado el hardware, con lo cual, es casi seguro que al intentar cargar el módulo te dé un error y por consiguiente, tendrás que compilar el fuente de ese módulo para que funcione en ese kernel. Vamos a ver los pasos necesarios:

1.- Necesitaremos tener el código fuente del núcleo. En mi caso (CentOS 5.3) deberemos buscar en el siguiente enlace http://vault.centos.org/ la versión exacta de nuestro kernel.
$ uname -r

En mi caso aparece lo siguiente:
2.6.18-128.el5

Buscaremos por el enlace que hemos indicado antes hasta encontrar el que nos hace falta, en mi caso sería:
kernel-2.6.18-128.el5.src.rpm

Ahora que ya tenemos el kernel necesario solo hace falta hacer lo siguiente:
$ rpm -Uvh kernel-2.6.18-128.el5.src.rpm
$ cd /usr/src/redhat/SPECS
$ rpmbuild -bp --target i386 kernel-2.6.spec

Con esto ya tenemos las fuentes del núcleo, concretamente en /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i386/ (por lo menos en mi caso).

2.- Ahora toca proceder con la compilación en sí. Para ello vamos a utilizar un módulo de ejemplo. Crearemos un directorio nuevo en la rama del kernel, por ejemplo, "demo". Dentro de ese directorio crearemos un fichero:
$ vi Makefile

Añadimos lo siguiente:
obj-m:= hola.o
KERNEL = $(shell uname -r)
all:
make -C /lib/modules/$(KERNEL)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KERNEL)/build M=$(PWD) clean

3.- Ya tenemos el fichero "Makefile". Hay que tener en cuenta que donde pone "hola.o" hay que poner el nombre del fichero que vamos a compilar, pero en vez de .c poner .o. En nuestro caso, como veremos a continuación el fichero fuente será "hola.c" y será tal y como vemos a continuación (dentro del directorio "demo"):
#include 
#include

MODULE_LICENSE("Dual BSD/GLP");

static int hola_init(void)
{
printk(KERN_ALERT "Cargando el modulo hola...\n");
return 0;
}

static void hola_exit(void)
{
printk(KERN_ALERT "Descargando el modulo hola...\n");
}

module_init(hola_init);
module_exit(hola_exit);

4.- Ya tenemos todo lo necesario para compilar el módulo, en nuestro caso tenemos el fichero "hola.c" en el caso de que fuese un fuente suministrador por el fabricante de hardware pues sería lo mismo pero cambiando los nombres correspondientes. Bien, para compilar simplemente hay que ejecutar el comando "make":
$ Make

5.- Una vez compilado solo queda cargar el módulo (como root), en nuestro caso sería así:
# insmod hola.ko

6.- Sólo queda verificar que el módulo está cargado:
# lsmod |grep hola
hola 5504 0

o también, en nuestro nuestro módulo hola.ko, viendo el mensaje que nos aparece en el log del sistema:
# tail -f /var/log/messages

Que nos mostrará lo siguiente:
Jan  1 12:21:20 centos53 kernel: Cargando el modulo hola...

7.- Para descargar el módulo del kernel ejecutamos lo siguiente:
# rmmod hola.ko

8.- Solo recordar que deberéis copiar el módulo en /lib. Crearemos un directorio donde corresponda y copiamos el fichero allí:
# mkdir -p /lib/modules/$(uname -r)/kernel/drivers/hola
# cp hola.ko /lib/modules/$(uname -r)/kernel/drivers/hola/

Añadir la entrada que corresponde en /etc/modprobe.conf:
alias hola hola

Ejecutamos:
# depmod -a

Con esto nos basta ejecutar lo siguiente para cargar el módulo:
# modprobe hola

Saludos.