logo

Linux Kernel Module Programmering: Hello World Program

Kärnmoduler är kodbitar som kan laddas och laddas ur i kärnan på begäran. De utökar kärnans funktionalitet utan att behöva starta om systemet. Anpassade koder kan läggas till Linux-kärnor via två metoder.
  • Det grundläggande sättet är att lägga till koden i kärnans källträd och kompilera om kärnan.
  • Ett mer effektivt sätt är att göra detta genom att lägga till kod till kärnan medan den körs. Denna process kallas att ladda modulen där modulen refererar till koden som vi vill lägga till i kärnan.
Eftersom vi laddar dessa koder vid körning och de inte är en del av den officiella Linux-kärnan kallas dessa loadable kernel module (LKM) som skiljer sig från baskärnan. Baskärnan finns i /boot-katalogen och laddas alltid när vi startar vår maskin medan LKM:er laddas efter att baskärnan redan är laddad. Ändå är dessa LKM i hög grad en del av vår kärna och de kommunicerar med baskärnan för att slutföra sina funktioner. LKMs kan utföra en mängd olika uppgifter men i grund och botten delas de in i tre huvudkategorier
  • enhetsdrivrutin
  • filsystemdrivrutin och
  • Systemsamtal.
Så vilken fördel erbjuder LKM? En stor fördel de har är att vi inte behöver fortsätta bygga om kärnan varje gång vi lägger till en ny enhet eller om vi uppgraderar en gammal enhet. Detta sparar tid och hjälper också till att hålla vår baskärna felfri. En användbar tumregel är att vi inte ska ändra vår baskärna när vi väl har en fungerande baskärna. Det hjälper också till att diagnostisera systemproblem. Anta till exempel att vi har lagt till en modul till baskärnan (dvs vi har modifierat vår baskärna genom att kompilera om den) och modulen har en bugg i sig. Detta kommer att orsaka fel vid systemstart och vi kommer aldrig att veta vilken del av kärnan som orsakar problem. Om vi ​​laddar modulen vid körning och det orsakar problem kommer vi omedelbart att känna till problemet och vi kan ladda ner modulen tills vi fixar det. LKM:er är mycket flexibla i den meningen att de kan laddas och lossas med en enda kommandorad. Detta hjälper till att spara minne eftersom vi laddar LKM endast när vi behöver dem. Dessutom är de inte långsammare än baskärnan eftersom att anropa någon av dem helt enkelt laddar kod från en annan del av minnet. **Varning: LKM är inte användarrymdprogram. De är en del av kärnan. De har fri körning av systemet och kan lätt krascha 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 worldn');  return 0; } static void __exit hello_end(void) {  printk(KERN_INFO 'Goodbye Mr.n'); } module_init(hello_start); module_exit(hello_end); 
Förklaring till ovanstående kod: Kärnmoduler måste ha minst två funktioner: en 'start' (initiering) funktion som heter init_module() som anropas när modulen är inbyggd i kärnan och en 'end' (cleanup) funktion som heter cleanup_module() som anropas precis innan den är rmmoded. Saker och ting har faktiskt förändrats från och med kärnan 2.3.13. Du kan nu använda vilket namn du vill för start- och slutfunktionerna för en modul. I själva verket är den nya metoden den föredragna metoden. Men många använder fortfarande init_module() och cleanup_module() för sina start- och slutfunktioner. I den här koden har vi använt hello_start() som init-funktion och hello_end() som rensningsfunktion. En annan sak som du kanske har lagt märke till är att istället för printf()-funktionen har vi använt printk(). Detta beror på att modulen inte kommer att skriva ut något på konsolen men den kommer att logga meddelandet i /var/log/kern.log. Därför används den för att felsöka kärnmoduler. Dessutom finns det åtta möjliga loggnivåsträngar definierade i rubriken som krävs när du använder printk(). Vi har listat dem i ordning efter minskande svårighetsgrad:
  • KERN_EMERG: Används för nödmeddelanden vanligtvis de som föregår en krasch.
  • KERN_ALERT: En situation som kräver omedelbar åtgärd.
  • KERN_CRIT: Kritiska tillstånd ofta relaterade till allvarliga hårdvaru- eller mjukvarufel.
  • KERN_ERR: Används för att rapportera feltillstånd; enhetsdrivrutiner använder ofta KERN_ERR för att rapportera hårdvaruproblem.
  • KERN_VARNING: Varningar om problematiska situationer som inte i sig skapar allvarliga problem med systemet.
  • KERN_NOTICE: Situationer som är normala men ändå värda att notera. Ett antal säkerhetsrelaterade tillstånd rapporteras på denna nivå.
  • KERN_INFO: Informationsmeddelanden. Många drivrutiner skriver ut information om hårdvaran de hittar vid uppstart på denna nivå.
  • KERN_DEBUG: Används för att felsöka meddelanden.
  • Vi har använt KERN_INFO för att skriva ut meddelandet. Förbereder systemet för att köra 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 för att kompilera källkoden:
    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 
    **Obs: Glöm inte tabbutrymmena i Makefile Kompilera och ladda modulen: 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 
    Testa modulen: 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.