logo

Programiranje modula jezgre Linuxa: program Hello World

Moduli kernela su dijelovi koda koji se mogu učitati i iskrcati u kernel na zahtjev. Proširuju funkcionalnost kernela bez potrebe za ponovnim pokretanjem sustava. Prilagođeni kodovi mogu se dodati Linux kernelima putem dvije metode.
  • Osnovni način je dodavanje koda izvornom stablu kernela i ponovno kompajliranje kernela.
  • Učinkovitiji način je da to učinite dodavanjem koda u kernel dok radi. Taj se proces naziva učitavanje modula gdje se modul odnosi na kod koji želimo dodati kernelu.
Budući da ove kodove učitavamo tijekom izvođenja i oni nisu dio službene jezgre Linuxa, oni se nazivaju učitati modul jezgre (LKM) koji se razlikuje od osnovne jezgre. Osnovni kernel nalazi se u direktoriju /boot i uvijek se učitava kada dižemo naš stroj, dok se LKM-ovi učitavaju nakon što je osnovni kernel već učitan. Bez obzira na to, ti su LKM-ovi u velikoj mjeri dio naše jezgre i komuniciraju s osnovnom jezgrom kako bi dovršili svoje funkcije. LKM-ovi mogu obavljati različite zadatke, ali u osnovi se mogu podijeliti u tri glavne kategorije
  • upravljački program uređaja
  • upravljački program datotečnog sustava i
  • Sistemski pozivi.
Dakle, kakvu prednost nude LKM-ovi? Jedna velika prednost koju imaju je ta da ne moramo stalno obnavljati kernel svaki put kada dodamo novi uređaj ili ako nadogradimo stari uređaj. Ovo štedi vrijeme i također pomaže u održavanju naše osnovne jezgre bez grešaka. Korisno pravilo je da ne bismo trebali mijenjati našu osnovnu jezgru nakon što imamo radnu osnovnu jezgru. Također pomaže u dijagnosticiranju problema u sustavu. Na primjer, pretpostavimo da smo dodali modul osnovnoj jezgri (tj. izmijenili smo svoju osnovnu jezgru ponovnim kompajliranjem) i da modul ima grešku u sebi. To će uzrokovati pogrešku pri pokretanju sustava i nikada nećemo znati koji dio kernela uzrokuje probleme. Dok ako učitamo modul tijekom izvođenja i on uzrokuje probleme, odmah ćemo znati problem i možemo isprazniti modul dok ga ne popravimo. LKM-ovi su vrlo fleksibilni u smislu da se mogu puniti i istovarati s jednom linijom naredbe. Ovo pomaže u uštedi memorije jer učitavamo LKM samo kada su nam potrebni. Štoviše, nisu sporiji od osnovne jezgre jer pozivanje bilo kojeg od njih jednostavno učitava kod iz drugog dijela memorije. **Upozorenje: LKM-ovi nisu korisnički svemirski programi. Oni su dio kernela. Oni imaju slobodan rad sa sustavom i lako ga mogu srušiti. 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); 
Objašnjenje za gornji kôd: Moduli kernela moraju imati najmanje dvije funkcije: funkciju 'starta' (inicijalizacije) koja se zove init_module() koja se poziva kada je modul insmodiran u kernel i funkciju 'end' (čišćenje) koja se zove cleanup_module() koja se poziva neposredno prije nego što se modulira. Stvari su se zapravo promijenile počevši od kernela 2.3.13. Sada možete koristiti bilo koje ime za početnu i završnu funkciju modula. U stvari, nova metoda je preferirana metoda. Međutim, mnogi ljudi još uvijek koriste init_module() i cleanup_module() za svoje početne i završne funkcije. U ovom kodu koristili smo hello_start() kao init funkciju i hello_end() kao funkciju čišćenja. Još jedna stvar koju ste mogli primijetiti je da smo umjesto funkcije printf() koristili printk(). To je zato što modul neće ispisati ništa na konzoli, ali će zabilježiti poruku u /var/log/kern.log. Stoga se koristi za ispravljanje pogrešaka modula jezgre. Štoviše, postoji osam mogućih nizova razine logiranja definiranih u zaglavlju koji su potrebni za korištenje printk(). Naveli smo ih prema padajućoj ozbiljnosti:
  • KERN_EMERG: Koristi se za hitne poruke obično one koje prethode padu.
  • KERN_ALERT: Situacija koja zahtijeva hitnu akciju.
  • KERN_CRIT: Kritični uvjeti često povezani s ozbiljnim kvarovima hardvera ili softvera.
  • KERN_ERR: Koristi se za prijavu stanja pogreške; upravljački programi uređaja često koriste KERN_ERR za prijavu hardverskih poteškoća.
  • KERN_WARNING: Upozorenja o problematičnim situacijama koje same po sebi ne stvaraju ozbiljne probleme sa sustavom.
  • KERN_NOTICE: Situacije koje su normalne, ali ipak vrijedne pažnje. Na ovoj se razini prijavljuje niz sigurnosnih uvjeta.
  • KERN_INFO: Informativne poruke. Mnogi upravljački programi ispisuju informacije o hardveru koji pronađu prilikom pokretanja na ovoj razini.
  • KERN_DEBUG: Koristi se za poruke za otklanjanje pogrešaka.
  • Koristili smo KERN_INFO za ispis poruke. Priprema sustava za izvođenje koda: 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 kompajliranje izvornog koda:
    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 
    **Napomena: Ne zaboravite prostore kartica u Makefileu Kompajliranje i učitavanje 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.