logo

Programació del mòdul del nucli de Linux: programa Hello World

Els mòduls del nucli són fragments de codi que es poden carregar i descarregar al nucli a petició. Amplien la funcionalitat del nucli sense necessitat de reiniciar el sistema. Els codis personalitzats es poden afegir als nuclis de Linux mitjançant dos mètodes.
  • La manera bàsica és afegir el codi a l'arbre font del nucli i recompilar el nucli.
  • Una manera més eficient de fer-ho és afegint codi al nucli mentre s'està executant. Aquest procés s'anomena carregar el mòdul on el mòdul fa referència al codi que volem afegir al nucli.
Com que estem carregant aquests codis en temps d'execució i no formen part del nucli oficial de Linux, s'anomenen mòdul de nucli carregable (LKM) que és diferent del nucli base. El nucli base es troba al directori /boot i sempre es carrega quan arrenquem la nostra màquina, mentre que els LKM es carreguen després que el nucli base ja estigui carregat. No obstant això, aquests LKM formen part molt del nostre nucli i es comuniquen amb el nucli base per completar les seves funcions. Els LKM poden realitzar una varietat de tasques, però bàsicament es divideixen en tres categories principals
  • controlador del dispositiu
  • controlador del sistema de fitxers i
  • Trucades del sistema.
Aleshores, quin avantatge ofereixen els LKM? Un dels principals avantatges que tenen és que no hem de continuar reconstruint el nucli cada vegada que afegim un dispositiu nou o si actualitzem un dispositiu antic. Això estalvia temps i també ajuda a mantenir lliure d'errors del nucli base. Una regla general útil és que no hem de canviar el nostre nucli base un cop tinguem un nucli base que funcioni. També ajuda a diagnosticar problemes del sistema. Per exemple, suposem que hem afegit un mòdul al nucli base (és a dir, hem modificat el nostre nucli base recompilant-lo) i el mòdul té un error. Això provocarà errors a l'arrencada del sistema i mai sabrem quina part del nucli està causant problemes. Mentre que si carreguem el mòdul en temps d'execució i causa problemes immediatament sabrem el problema i podrem descarregar el mòdul fins que ho solucionem. Els LKM són molt flexibles en el sentit que es poden carregar i descarregar amb una única línia de comandament. Això ajuda a estalviar memòria ja que carreguem el LKM només quan els necessitem. A més, no són més lents que el nucli base perquè cridar a qualsevol d'ells és simplement carregar codi d'una part diferent de la memòria. **Avís: els LKM no són programes d'espai d'usuari. Formen part del nucli. Tenen l'execució lliure del sistema i poden bloquejar-lo fàcilment. 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ó del codi anterior: Els mòduls del nucli han de tenir almenys dues funcions: una funció d'inici (inicialització) anomenada init_module() que s'anomena quan el mòdul s'instal·la al nucli i una funció de finalització (neteja) anomenada cleanup_module() que es crida just abans de ser rmmoded. De fet, les coses han canviat a partir del nucli 2.3.13. Ara podeu utilitzar el nom que vulgueu per a les funcions d'inici i finalització d'un mòdul. De fet, el nou mètode és el mètode preferit. No obstant això, molta gent encara utilitza init_module() i cleanup_module() per a les seves funcions inicial i final. En aquest codi hem utilitzat hello_start() com a funció d'inici i hello_end() com a funció de neteja. Una altra cosa que potser haureu notat és que en comptes de la funció printf() hem utilitzat printk(). Això és perquè el mòdul no imprimirà res a la consola, però registrarà el missatge a /var/log/kern.log. Per tant, s'utilitza per depurar mòduls del nucli. A més, hi ha vuit possibles cadenes de nivell de registre definides a la capçalera que es requereixen quan s'utilitza printk(). Els hem enumerat per ordre decreixent de gravetat:
  • KERN_EMERG: s'utilitza per als missatges d'emergència generalment els que precedeixen un accident.
  • KERN_ALERT: una situació que requereix una acció immediata.
  • KERN_CRIT: condicions crítiques sovint relacionades amb errors greus de maquinari o programari.
  • KERN_ERR: S'utilitza per informar de condicions d'error; Els controladors de dispositiu sovint utilitzen KERN_ERR per informar de problemes de maquinari.
  • KERN_WARNING: Avisos sobre situacions problemàtiques que per si mateixes no creen problemes greus amb el sistema.
  • KERN_NOTICE: Situacions normals però dignes de tenir en compte. En aquest nivell s'informa d'una sèrie de condicions relacionades amb la seguretat.
  • KERN_INFO: Missatges informatius. Molts controladors imprimeixen informació sobre el maquinari que troben en el moment de l'inici en aquest nivell.
  • KERN_DEBUG: S'utilitza per depurar missatges.
  • Hem utilitzat KERN_INFO per imprimir el missatge. Preparant el sistema per executar el codi: 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 per compilar el codi font:
    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 oblideu els espais de pestanya a Makefile Compilació i càrrega del mòdul: 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 
    Prova el mòdul: 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.