Cuando se inserta un módulo en el kernel, lo primero que hace el kernel es ejecutar la función init_module() que se supone ha de estar definida en el módulo. En esta función el módulo ha de informar al kernel de sus capacidades, describiéndole las funciones que implementa. El kernel recibe todos esos datos y los almacena en una tabla para cuando más tarde necesite de alguna función del módulo.
Tan importante como init_module() es cleanup_module() , que es ejecutada por el kernel cuando eliminas el módulo. En ella el módulo le dice al kernel que ya no va a estar con él y que todas aquellas operaciones que antes le dijimos que era capaz de hacer, ya no las va a implementar nadie.
Si eliminamos un módulo en el que cleanup_module() no da de baja todas las funcionalidades que init_module() dio de alta, entonces el kernel creerá que hay ciertas cosas que un módulo puede hacer, sin embargo ese módulo ya no está en memoria, por lo que si intenta usar una de esas funcionalidades el kernel se caerá y tendremos que reiniciar el ordenador.
Para ilustrar el uso de estas dos funciones vamos a programar un sencillo módulo que lo único que hace es imprimir por la salida estándar del kernel (/var/log/messages) un sencillo mensaje. Como este módulo no implementa ninguna operación adicional, init_module() no debe dar de alta ninguna funcionalidad.
/* módulo hola.c */ #define __KERNEL__ #define MODULE #include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk("hola: hola mundo\n"); return 0; } void cleanup_module(void) { printk("hola: adios mundo\n"); }
Lo primero que hacemos cuando estamos programando un módulo es incluir el fichero de cabeceras /linux/module.h, donde se definen un montón de macros que nos serán necesarias para la programación de módulos. Todo módulo ha de tener incluido este fichero. Además es necesario definir los símbolos para el preprocesador __KERNEL__ y MODULE , que nos permiten acceder a todas las macros definidas en los ficheros de cabeceras del kernel que tienen que ver con módulos4.5.
A continuación implementamos la función init_module(), no es necesario declararla pues ya lo hace indirectamente /linux/module.h.
En este ejemplo aparece la función printk() , esta definida en el kernel en el fichero de cabeceras /linux/kernel.h. Nótese que este fichero ya ha sido incluido en nuestro ejemplo.
Por último codificamos cleanup_module(), que simplemente hace uso de printk() para dar un mensaje de despedida.