logo

Programación del módulo del kernel de Linux: programa Hola Mundo

Los módulos del kernel son fragmentos de código que se pueden cargar y descargar en el kernel según sea necesario. Amplían la funcionalidad del kernel sin necesidad de reiniciar el sistema. Se pueden agregar códigos personalizados a los kernels de Linux mediante dos métodos.
  • La forma básica es agregar el código al árbol fuente del kernel y recompilar el kernel.
  • Una forma más eficiente de hacerlo es agregando código al kernel mientras se está ejecutando. Este proceso se llama cargar el módulo donde módulo se refiere al código que queremos agregar al kernel.
Dado que cargamos estos códigos en tiempo de ejecución y no son parte del kernel oficial de Linux, se denominan módulo de kernel cargable (LKM), que es diferente del kernel base. El kernel base se encuentra en el directorio /boot y siempre se carga cuando arrancamos nuestra máquina, mientras que los LKM se cargan después de que el kernel base ya esté cargado. No obstante, estos LKM son en gran medida parte de nuestro kernel y se comunican con el kernel base para completar sus funciones. Los LKM pueden realizar una variedad de tareas, pero básicamente se dividen en tres categorías principales.
  • controlador de dispositivo
  • controlador del sistema de archivos y
  • Llamadas al sistema.
Entonces, ¿qué ventaja ofrecen los LKM? Una de las principales ventajas que tienen es que no necesitamos seguir reconstruyendo el kernel cada vez que agregamos un nuevo dispositivo o si actualizamos un dispositivo antiguo. Esto ahorra tiempo y también ayuda a mantener nuestro kernel base libre de errores. Una regla general útil es que no debemos cambiar nuestro kernel base una vez que tengamos un kernel base funcional. También ayuda a diagnosticar problemas del sistema. Por ejemplo, supongamos que hemos agregado un módulo al kernel base (es decir, hemos modificado nuestro kernel base recompilándolo) y el módulo tiene un error. Esto provocará un error en el arranque del sistema y nunca sabremos qué parte del kernel está causando los problemas. Mientras que si cargamos el módulo en tiempo de ejecución y causa problemas, sabremos inmediatamente el problema y podremos descargar el módulo hasta que lo solucionemos. Los LKM son muy flexibles en el sentido de que se pueden cargar y descargar con una sola línea de comando. Esto ayuda a ahorrar memoria ya que cargamos el LKM solo cuando lo necesitamos. Además, no son más lentos que el kernel base porque llamar a cualquiera de ellos es simplemente cargar código desde una parte diferente de la memoria. **Advertencia: Los LKM no son programas de espacio de usuario. Son parte del núcleo. Tienen libertad de ejecución del sistema y pueden bloquearlo fácilmente. So now that we have established the use loadable kernel modules we are going to write a hello world kernel module. That will print a message when we load the module and an exit message when we unload the module. Code: CPP
/**  * @file hello.c  * @author Akshat Sinha  * @date 10 Sept 2016  * @version 0.1  * @brief An introductory 'Hello World!' loadable kernel  * module (LKM) that can display a message in the /var/log/kern.log  * file when the module is loaded and removed. The module can accept  * an argument when it is loaded -- the name which appears in the  * kernel log files. */ #include  /* Needed by all modules */ #include  /* Needed for KERN_INFO */ #include  /* Needed for the macros */ ///< The license type -- this affects runtime behavior MODULE_LICENSE('GPL'); ///< The author -- visible when you use modinfo MODULE_AUTHOR('Akshat Sinha'); ///< The description -- see modinfo MODULE_DESCRIPTION('A simple Hello world LKM!'); ///< The version of the module MODULE_VERSION('0.1'); static int __init hello_start(void) {  printk(KERN_INFO 'Loading hello module...n');  printk(KERN_INFO 'Hello worldn');  return 0; } static void __exit hello_end(void) {  printk(KERN_INFO 'Goodbye Mr.n'); } module_init(hello_start); module_exit(hello_end); 
Explicación del código anterior: Los módulos del kernel deben tener al menos dos funciones: una función de 'inicio' (inicialización) llamada init_module() que se llama cuando el módulo se inserta en el kernel y una función de 'fin' (limpieza) llamada cleanup_module() que se llama justo antes de que se modifique. En realidad, las cosas han cambiado a partir del kernel 2.3.13. Ahora puede usar el nombre que desee para las funciones de inicio y finalización de un módulo. De hecho, el nuevo método es el método preferido. Sin embargo, muchas personas todavía usan init_module() y cleanup_module() para sus funciones de inicio y finalización. En este código hemos utilizado hello_start() como función de inicio y hello_end() como función de limpieza. Otra cosa que quizás hayas notado es que en lugar de la función printf() hemos usado printk(). Esto se debe a que el módulo no imprimirá nada en la consola pero registrará el mensaje en /var/log/kern.log. Por lo tanto, se utiliza para depurar módulos del kernel. Además, hay ocho posibles cadenas de nivel de registro definidas en el encabezado que se requieren al usar printk(). Los hemos enumerado en orden de gravedad decreciente:
  • KERN_EMERG: Se utiliza para mensajes de emergencia, normalmente aquellos que preceden a un bloqueo.
  • KERN_ALERT: Una situación que requiere acción inmediata.
  • KERN_CRIT: Condiciones críticas a menudo relacionadas con fallos graves de hardware o software.
  • KERN_ERR: se utiliza para informar condiciones de error; Los controladores de dispositivos suelen utilizar KERN_ERR para informar dificultades de hardware.
  • KERN_WARNING: Advertencias sobre situaciones problemáticas que por sí solas no crean problemas graves en el sistema.
  • KERN_NOTICE: Situaciones que son normales pero aún así dignas de mención. En este nivel se informan una serie de condiciones relacionadas con la seguridad.
  • KERN_INFO: Mensajes informativos. Muchos controladores imprimen información sobre el hardware que encuentran en el momento del inicio en este nivel.
  • KERN_DEBUG: Se utiliza para depurar mensajes.
  • Hemos utilizado KERN_INFO para imprimir el mensaje. Preparando el sistema para ejecutar el código: The system must be prepared to build kernel code and to do this you must have the Linux headers installed on your device. On a typical Linux desktop machine you can use your package manager to locate the correct package to install. For example under 64-bit Debian you can use:
    akshat@gfg:~$ sudo apt-get install build-essential linux-headers-$(uname -r) 
    Makefile para compilar el código fuente:
    obj-m = hello.o all: make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 
    **Nota: No olvides los espacios de tabulación en Makefile Compilando y cargando el módulo: Run the make command to compile the source code. Then use insmod to load the module.
    akshat@gfg:~$ make make -C /lib/modules/4.2.0-42-generic/build/ M=/home/akshat/Documents/hello-module modules make[1]: Entering directory `/usr/src/linux-headers-4.2.0-42-generic' CC [M] /home/akshat/Documents/hello-module/hello.o Building modules stage 2. MODPOST 1 modules CC /home/akshat/Documents/hello-module/hello.mod.o LD [M] /home/akshat/Documents/hello-module/hello.ko make[1]: Leaving directory `/usr/src/linux-headers-4.2.0-42-generic' 
    Now we will use insmod to load the hello.ko object.
    akshat@gfg:~$ sudo insmod hello.ko 
    Probando el módulo: You can get information about the module using the modinfo command which will identify the description author and any module parameters that are defined:
    akshat@gfg:~$ modinfo hello.ko filename: /home/akshat/Documents/hello-module/hello.ko version: 0.1 description: A simple Hello world LKM author: Akshat Sinha license: GPL srcversion: 2F2B1B95DA1F08AC18B09BC depends: vermagic: 4.2.0-42-generic SMP mod_unload modversions 
    To see the message we need to read the kern.log in /var/log directory.
    akshat@gfg:~$ tail /var/log/kern.log ... ... Sep 10 17:43:39 akshat-gfg kernel: [26380.327886] Hello world To unload the module we run rmmod: akshat@gfg:~$ sudo rmmod hello Now run the tail command to get the exit message. akshat@gfg:~$ tail /var/log/kern.log ... Sep 10 17:43:39 akshat-gfg kernel: [26380.327886] Hello world Sep 10 17:45:42 akshat-gfg kernel: [26503.773982] Goodbye Mr.