Linux Kernel Modul Programmering: Hello World Program

Kernelmoduler er stykker kode, der kan indlæses og losses i kernen efter behov. De udvider kernens funktionalitet uden at skulle genstarte systemet. Brugerdefinerede koder kan tilføjes til Linux-kerner via to metoder.
  • Den grundlæggende måde er at tilføje koden til kernens kildetræ og genkompilere kernen.
  • En mere effektiv måde er at gøre dette ved at tilføje kode til kernen, mens den kører. Denne proces kaldes indlæsning af modulet, hvor modulet refererer til den kode, som vi ønsker at tilføje til kernen.
Da vi indlæser disse koder under kørsel, og de ikke er en del af den officielle Linux-kerne, kaldes disse loadable kernel module (LKM), som er forskellig fra basiskernen. Basiskernen er placeret i /boot-mappen og indlæses altid, når vi starter vores maskine, hvorimod LKM'er indlæses, efter at basiskernen allerede er indlæst. Ikke desto mindre er disse LKM i høj grad en del af vores kerne, og de kommunikerer med basiskernen for at fuldføre deres funktioner. LKM'er kan udføre en række opgaver, men dybest set falder de ind under tre hovedkategorier
  • enhedsdriver
  • filsystem driver og
  • Systemopkald.
Så hvilken fordel tilbyder LKM'er? En stor fordel, de har, er, at vi ikke behøver at blive ved med at genopbygge kernen, hver gang vi tilføjer en ny enhed, eller hvis vi opgraderer en gammel enhed. Dette sparer tid og hjælper også med at holde vores basiskerne fejlfri. En nyttig tommelfingerregel er, at vi ikke skal ændre vores basiskerne, når vi først har en fungerende basiskerne. Det hjælper også med at diagnosticere systemproblemer. Antag for eksempel, at vi har tilføjet et modul til basiskernen (dvs. vi har ændret vores basiskerne ved at genkompilere den), og modulet har en fejl i sig. Dette vil forårsage fejl i systemstart, og vi vil aldrig vide, hvilken del af kernen, der forårsager problemer. Hvorimod hvis vi indlæser modulet under kørsel, og det forårsager problemer, vil vi straks kende problemet, og vi kan aflæse modulet, indtil vi løser det. LKM'er er meget fleksible i den forstand, at de kan indlæses og losses med en enkelt kommandolinje. Dette hjælper med at spare hukommelse, da vi kun indlæser LKM, når vi har brug for dem. Desuden er de ikke langsommere end basiskernen, fordi at kalde en af ​​dem blot er at indlæse kode fra en anden del af hukommelsen. **Advarsel: LKM'er er ikke brugerrumsprogrammer. De er en del af kernen. De har fri kørsel af systemet og kan nemt crashe det. 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 world  n  '  );      return     0  ;   }   static     void     __exit     hello_end  (  void  )   {      printk  (  KERN_INFO     'Goodbye Mr.  n  '  );   }   module_init  (  hello_start  );   module_exit  (  hello_end  );   
Forklaring på ovenstående kode: Kernelmoduler skal have mindst to funktioner: en 'start' (initialisering) funktion kaldet init_module() som kaldes når modulet er insmoded i kernen og en 'end' (cleanup) funktion kaldet cleanup_module(), som kaldes lige før det er rmmoded. Faktisk har tingene ændret sig fra kerne 2.3.13. Du kan nu bruge et hvilket som helst navn til start- og slutfunktionerne for et modul. Faktisk er den nye metode den foretrukne metode. Men mange mennesker bruger stadig init_module() og cleanup_module() til deres start- og slutfunktioner. I denne kode har vi brugt hello_start() som init-funktion og hello_end() som oprydningsfunktion. En anden ting, som du måske har bemærket, er, at i stedet for printf()-funktionen har vi brugt printk(). Dette skyldes, at modulet ikke udskriver noget på konsollen, men det vil logge beskeden i /var/log/kern.log. Derfor bruges det til at fejlsøge kernemoduler. Desuden er der otte mulige loglevel-strenge defineret i headeren, som er nødvendige, mens du bruger printk(). Vi har listet dem i rækkefølge efter faldende sværhedsgrad:
  • KERN_EMERG: Bruges til nødbeskeder, normalt dem, der går forud for et nedbrud.
  • KERN_ALERT: En situation, der kræver øjeblikkelig handling.
  • KERN_CRIT: Kritiske forhold ofte relateret til alvorlige hardware- eller softwarefejl.
  • KERN_ERR: Bruges til at rapportere fejltilstande; enhedsdrivere bruger ofte KERN_ERR til at rapportere hardwareproblemer.
  • KERN_WARNING: Advarsler om problematiske situationer, der ikke i sig selv skaber alvorlige problemer med systemet.
  • KERN_NOTICE: Situationer, der er normale, men som stadig er værd at bemærke. En række sikkerhedsrelaterede forhold rapporteres på dette niveau.
  • KERN_INFO: Informationsmeddelelser. Mange drivere udskriver oplysninger om den hardware, de finder ved opstart på dette niveau.
  • KERN_DEBUG: Bruges til fejlretning af meddelelser.
  • Vi har brugt KERN_INFO til at udskrive beskeden. Forberedelse af systemet til at køre koden: 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 til at kompilere kildekoden:
    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  
    **Bemærk: Glem ikke tabulatorrummene i Makefile Kompilering og indlæsning af modulet: 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  
    Test af modulet: 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.