logo

Programiranje modula jedra Linuxa: program Hello World

Moduli jedra so deli kode, ki jih je mogoče na zahtevo naložiti in razložiti v jedro. Razširijo funkcionalnost jedra brez potrebe po ponovnem zagonu sistema. Kode po meri lahko jedrom Linux dodate na dva načina.
  • Osnovni način je, da dodate kodo v izvorno drevo jedra in ponovno prevedete jedro.
  • Učinkovitejši način za to je dodajanje kode v jedro med izvajanjem. Ta postopek se imenuje nalaganje modula, kjer se modul nanaša na kodo, ki jo želimo dodati v jedro.
Ker te kode nalagamo med izvajanjem in niso del uradnega jedra Linuxa, se imenujejo modul jedra, ki ga je mogoče naložiti (LKM), ki se razlikuje od osnovnega jedra. Osnovno jedro se nahaja v imeniku /boot in se vedno naloži, ko zaženemo naš stroj, medtem ko se LKM-ji naložijo, ko je osnovno jedro že naloženo. Kljub temu so ti LKM v veliki meri del našega jedra in komunicirajo z osnovnim jedrom, da dokončajo svoje funkcije. LKM lahko opravljajo različne naloge, vendar so v bistvu razdeljeni v tri glavne kategorije
  • gonilnik naprave
  • gonilnik datotečnega sistema in
  • Sistemski klici.
Kakšno prednost torej ponujajo LKM? Njihova velika prednost je ta, da nam ni treba nenehno obnavljati jedra vsakič, ko dodamo novo napravo ali če nadgradimo staro napravo. To prihrani čas in tudi pomaga pri ohranjanju našega osnovnega jedra brez napak. Koristno pravilo je, da ne smemo spreminjati osnovnega jedra, ko imamo delujoče osnovno jedro. Pomaga tudi pri diagnosticiranju sistemskih težav. Na primer, predpostavimo, da smo osnovnemu jedru dodali modul (tj. spremenili smo svoje osnovno jedro tako, da smo ga znova prevedli) in ima modul v sebi napako. To bo povzročilo napako pri zagonu sistema in nikoli ne bomo vedeli, kateri del jedra povzroča težave. Če pa modul naložimo med izvajanjem in povzroča težave, bomo takoj vedeli za težavo in lahko odstranimo modul, dokler ga ne popravimo. LKM so zelo prilagodljivi v smislu, da jih je mogoče naložiti in razložiti z eno samo ukazno vrstico. To pomaga pri varčevanju s pomnilnikom, saj naložimo LKM le, ko jih potrebujemo. Poleg tega niso počasnejša od osnovnega jedra, ker je klic enega od njih preprosto nalaganje kode iz drugega dela pomnilnika. **Opozorilo: LKM niso uporabniški prostorski programi. So del jedra. Imajo prosto delovanje sistema in ga zlahka sesujejo. 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); 
Razlaga zgornje kode: Moduli jedra morajo imeti vsaj dve funkciji: funkcijo 'začetek' (inicializacija), imenovano init_module(), ki se pokliče, ko je modul vstavljen v jedro, in funkcijo 'konca' (čiščenje), imenovano cleanup_module(), ki se pokliče tik preden je modul rmmoded. Pravzaprav so se stvari spremenile z jedrom 2.3.13. Zdaj lahko uporabite poljubno ime za začetno in končno funkcijo modula. Pravzaprav je nova metoda prednostna metoda. Vendar veliko ljudi še vedno uporablja init_module() in cleanup_module() za svoje začetne in končne funkcije. V tej kodi smo uporabili hello_start() kot init funkcijo in hello_end() kot funkcijo čiščenja. Druga stvar, ki ste jo morda opazili, je, da smo namesto funkcije printf() uporabili printk(). To je zato, ker modul ne bo natisnil ničesar na konzoli, ampak bo sporočilo zabeležil v /var/log/kern.log. Zato se uporablja za odpravljanje napak v modulih jedra. Poleg tega obstaja osem možnih nizov ravni dnevnika, definiranih v glavi, ki so potrebni med uporabo printk(). Našteli smo jih po padajoči resnosti:
  • KERN_EMERG: Uporablja se za sporočila v sili, običajno tista, ki so pred zrušitvijo.
  • KERN_ALERT: Situacija, ki zahteva takojšnje ukrepanje.
  • KERN_CRIT: Kritični pogoji, pogosto povezani z resnimi okvarami strojne ali programske opreme.
  • KERN_ERR: Uporablja se za poročanje o stanjih napak; gonilniki naprav pogosto uporabljajo KERN_ERR za poročanje o težavah s strojno opremo.
  • KERN_WARNING: Opozorila o problematičnih situacijah, ki same po sebi ne povzročajo resnih težav s sistemom.
  • KERN_NOTICE: Situacije, ki so običajne, a vseeno vredne pozornosti. Na tej ravni se poroča o številnih varnostnih pogojih.
  • KERN_INFO: Informativna sporočila. Mnogi gonilniki natisnejo informacije o strojni opremi, ki jo najdejo ob zagonu na tej ravni.
  • KERN_DEBUG: Uporablja se za sporočila o odpravljanju napak.
  • Za tiskanje sporočila smo uporabili KERN_INFO. Priprava sistema za izvajanje kode: 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 za prevajanje izvorne kode:
    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 
    **Opomba: Ne pozabite na prostore zavihkov v Makefile Prevajanje in nalaganje modula: 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 
    Testiranje modula: 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.