logo

Programovanie modulov Linuxového jadra: Program Hello World

Moduly jadra sú časti kódu, ktoré možno na požiadanie načítať a uvoľniť do jadra. Rozširujú funkčnosť jadra bez potreby reštartu systému. Vlastné kódy je možné pridať do linuxových jadier dvoma spôsobmi.
  • Základným spôsobom je pridať kód do zdrojového stromu jadra a prekompilovať jadro.
  • Efektívnejším spôsobom je pridať kód do jadra počas jeho spustenia. Tento proces sa nazýva načítanie modulu, kde modul odkazuje na kód, ktorý chceme pridať do jadra.
Keďže tieto kódy načítavame za behu a nie sú súčasťou oficiálneho jadra Linuxu, nazývajú sa načítateľný modul jadra (LKM), ktorý sa líši od základného jadra. Základné jadro sa nachádza v adresári /boot a načíta sa vždy, keď zavádzame náš počítač, zatiaľ čo LKM sa načítajú až po načítaní základného jadra. Napriek tomu sú tieto LKM z veľkej časti súčasťou nášho jadra a komunikujú so základným jadrom, aby dokončili svoje funkcie. LKM môžu vykonávať rôzne úlohy, ale v zásade spadajú do troch hlavných kategórií
  • ovládač zariadenia
  • ovládač súborového systému a
  • Systémové volania.
Akú výhodu teda LKM ponúkajú? Jednou z hlavných výhod, ktoré majú, je, že nemusíme neustále obnovovať jadro zakaždým, keď pridávame nové zariadenie alebo ak aktualizujeme staré zariadenie. To šetrí čas a tiež pomáha udržiavať naše základné jadro bez chýb. Užitočným pravidlom je, že by sme nemali meniť naše základné jadro, keď už máme funkčné základné jadro. Pomáha tiež pri diagnostike systémových problémov. Predpokladajme napríklad, že sme pridali modul do základného jadra (t. j. upravili sme naše základné jadro jeho rekompiláciou) a modul má v sebe chybu. To spôsobí chybu pri zavádzaní systému a nikdy nebudeme vedieť, ktorá časť jadra spôsobuje problémy. Zatiaľ čo ak načítame modul za behu a spôsobí to problémy, okamžite sa o probléme dozvieme a môžeme modul uvoľniť, kým ho neopravíme. LKM sú veľmi flexibilné v tom zmysle, že môžu byť načítané a uvoľňované pomocou jediného príkazového riadku. Pomáha to pri šetrení pamäte, pretože LKM načítavame iba vtedy, keď ich potrebujeme. Navyše nie sú pomalšie ako základné jadro, pretože volanie jedného z nich jednoducho načítava kód z inej časti pamäte. **Upozornenie: LKM nie sú programy používateľského priestoru. Sú súčasťou jadra. Majú voľný beh systému a môžu ho ľahko zrútiť. 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); 
Vysvetlenie vyššie uvedeného kódu: Moduly jadra musia mať aspoň dve funkcie: funkciu „štart“ (inicializáciu) nazývanú init_module(), ktorá sa volá, keď je modul vložený do jadra, a funkciu „konca“ (vyčistenie) nazývanú cleanup_module(), ktorá sa volá tesne pred tým, ako je modul rmmoded. V skutočnosti sa veci zmenili počnúc jadrom 2.3.13. Teraz môžete použiť ľubovoľný názov pre počiatočné a koncové funkcie modulu. V skutočnosti je nová metóda preferovanou metódou. Mnoho ľudí však stále používa init_module() a cleanup_module() pre svoje počiatočné a koncové funkcie. V tomto kóde sme použili hello_start() ako funkciu init a hello_end() ako funkciu čistenia. Ďalšia vec, ktorú ste si mohli všimnúť, je, že namiesto funkcie printf() sme použili printk(). Je to preto, že modul nevytlačí nič na konzole, ale zaznamená správu do /var/log/kern.log. Preto sa používa na ladenie modulov jadra. Okrem toho je v hlavičke definovaných osem možných reťazcov loglevel, ktoré sa vyžadujú pri použití printk(). Uvádzame ich v poradí podľa klesajúcej závažnosti:
  • KERN_EMERG: Používa sa pre núdzové správy, ktoré zvyčajne predchádzajú havárii.
  • KERN_ALERT: Situácia vyžadujúca okamžitú akciu.
  • KERN_CRIT: Kritické stavy často súvisia s vážnymi poruchami hardvéru alebo softvéru.
  • KERN_ERR: Používa sa na hlásenie chybových stavov; ovládače zariadení často používajú KERN_ERR na hlásenie problémov s hardvérom.
  • KERN_WARNING: Upozornenia na problematické situácie, ktoré samy osebe nespôsobujú vážne problémy so systémom.
  • KERN_NOTICE: Situácie, ktoré sú normálne, ale stále stoja za zmienku. Na tejto úrovni sa uvádza množstvo podmienok súvisiacich s bezpečnosťou.
  • KERN_INFO: Informačné správy. Mnoho ovládačov tlačí informácie o hardvéri, ktorý nájdu pri spustení na tejto úrovni.
  • KERN_DEBUG: Používa sa na ladenie správ.
  • Na tlač správy sme použili KERN_INFO. Príprava systému na spustenie kódu: 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 na kompiláciu zdrojového kódu:
    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 
    **Poznámka: Nezabudnite na medzery tabulátorov v Makefile Kompilácia a načítanie modulu: 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 
    Testovanie modulu: 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.