logo

Programarea modulului Linux Kernel: programul Hello World

Modulele kernel sunt bucăți de cod care pot fi încărcate și descărcate în nucleu la cerere. Acestea extind funcționalitatea nucleului fără a fi nevoie să reporniți sistemul. Codurile personalizate pot fi adăugate la nucleele Linux prin două metode.
  • Modul de bază este să adăugați codul în arborele sursă al nucleului și să recompilați nucleul.
  • O modalitate mai eficientă este de a face acest lucru este prin adăugarea de cod la nucleu în timp ce acesta rulează. Acest proces se numește încărcarea modulului unde modul se referă la codul pe care dorim să-l adăugăm la kernel.
Deoarece încărcăm aceste coduri în timpul execuției și nu fac parte din nucleul Linux oficial, acestea se numesc module de nucleu încărcat (LKM), care este diferit de nucleul de bază. Nucleul de bază se află în directorul /boot și este întotdeauna încărcat atunci când pornim mașina noastră, în timp ce LKM-urile sunt încărcate după ce nucleul de bază este deja încărcat. Cu toate acestea, aceste LKM fac parte din kernel-ul nostru și comunică cu nucleul de bază pentru a-și îndeplini funcțiile. LKM-urile pot îndeplini o varietate de sarcini, dar practic se încadrează în trei categorii principale
  • driver de dispozitiv
  • driverul sistemului de fișiere și
  • Apeluri de sistem.
Deci, ce avantaj oferă LKM-urile? Un avantaj major pe care îl au este că nu trebuie să continuăm să reconstruim nucleul de fiecare dată când adăugăm un dispozitiv nou sau dacă facem upgrade la un dispozitiv vechi. Acest lucru economisește timp și ajută, de asemenea, la menținerea erorilor de bază ale nucleului nostru. O regulă utilă este că nu ar trebui să ne schimbăm nucleul de bază odată ce avem un nucleu de bază funcțional. De asemenea, ajută la diagnosticarea problemelor sistemului. De exemplu, presupunem că am adăugat un modul la nucleul de bază (adică am modificat nucleul nostru de bază recompilându-l) și modulul are o eroare în el. Acest lucru va provoca o eroare la boot-ul sistemului și nu vom ști niciodată care parte a nucleului cauzează probleme. În timp ce dacă încărcăm modulul în timpul execuției și provoacă probleme, vom ști imediat problema și vom putea descărca modulul până când o remediam. LKM-urile sunt foarte flexibile în sensul că pot fi încărcate și descărcate cu o singură linie de comandă. Acest lucru ajută la economisirea memoriei, deoarece încărcăm LKM-ul numai atunci când avem nevoie de ele. În plus, ele nu sunt mai lente decât nucleul de bază, deoarece apelarea fiecăreia dintre ele înseamnă pur și simplu încărcarea codului dintr-o altă parte a memoriei. **Atenție: LKM-urile nu sunt programe pentru spațiul utilizatorului. Ele fac parte din nucleu. Au rularea liberă a sistemului și îl pot bloca cu ușurință. 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); 
Explicație pentru codul de mai sus: Modulele kernel trebuie să aibă cel puțin două funcții: o funcție „start” (inițializare) numită init_module() care este apelată atunci când modulul este insmoded în nucleu și o funcție „end” (curățare) numită cleanup_module() care este apelată chiar înainte de a fi rmmoded. De fapt, lucrurile s-au schimbat începând cu kernel-ul 2.3.13. Acum puteți folosi orice nume doriți pentru funcțiile de început și de sfârșit ale unui modul. De fapt, noua metodă este metoda preferată. Cu toate acestea, mulți oameni încă folosesc init_module() și cleanup_module() pentru funcțiile lor de pornire și de sfârșit. În acest cod am folosit hello_start() ca funcție init și hello_end() ca funcție de curățare. Un alt lucru pe care probabil l-ați observat este că în loc de funcția printf() am folosit printk(). Acest lucru se datorează faptului că modulul nu va imprima nimic pe consolă, dar va înregistra mesajul în /var/log/kern.log. Prin urmare, este folosit pentru a depana modulele nucleului. În plus, există opt șiruri de caractere loglevel posibile definite în antet care sunt necesare în timpul utilizării printk(). Le-am enumerat în ordinea descrescătoare a severității:
  • KERN_EMERG: Folosit pentru mesajele de urgență, de obicei, cele care preced un accident.
  • KERN_ALERT: O situație care necesită o acțiune imediată.
  • KERN_CRIT: Condiții critice legate adesea de erori grave de hardware sau software.
  • KERN_ERR: Folosit pentru a raporta condiții de eroare; Driverele de dispozitiv folosesc adesea KERN_ERR pentru a raporta dificultățile hardware.
  • KERN_WARNING: Avertismente despre situații problematice care nu creează în sine probleme serioase sistemului.
  • KERN_NOTICE: Situații care sunt normale, dar demne de reținut. La acest nivel sunt raportate o serie de condiții legate de securitate.
  • KERN_INFO: Mesaje informative. Mulți drivere imprimă informații despre hardware-ul pe care îl găsesc la momentul pornirii la acest nivel.
  • KERN_DEBUG: Folosit pentru depanarea mesajelor.
  • Am folosit KERN_INFO pentru a tipări mesajul. Pregătirea sistemului pentru a rula codul: 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 pentru a compila codul sursă:
    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 
    **Notă: nu uitați de spațiile de file din Makefile Compilarea și încărcarea modulului: 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 
    Testarea modulului: 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.