logo

Програмиране на модул на ядрото на Linux: програма Hello World

Модулите на ядрото са части от код, които могат да се зареждат и разтоварват в ядрото при поискване. Те разширяват функционалността на ядрото без необходимост от рестартиране на системата. Персонализираните кодове могат да се добавят към Linux ядрата чрез два метода.
  • Основният начин е да добавите кода към дървото на изходния код на ядрото и да прекомпилирате ядрото.
  • По-ефективен начин е да направите това е като добавите код към ядрото, докато то работи. Този процес се нарича зареждане на модула, където модулът се отнася до кода, който искаме да добавим към ядрото.
Тъй като ние зареждаме тези кодове по време на изпълнение и те не са част от официалното ядро ​​на Linux, те се наричат ​​зареждаем модул на ядрото (LKM), който е различен от основното ядро. Базовото ядро ​​се намира в /boot директория и винаги се зарежда, когато стартираме нашата машина, докато LKM се зареждат, след като базовото ядро ​​вече е заредено. Въпреки това тези LKM са част от нашето ядро ​​и те комуникират с основното ядро, за да изпълнят функциите си. LKM могат да изпълняват различни задачи, но основно те се разделят на три основни категории
  • драйвер на устройство
  • драйвер за файлова система и
  • Системни повиквания.
И така, какво предимство предлагат LKM? Едно основно предимство, което имат, е, че не е необходимо да продължаваме да възстановяваме ядрото всеки път, когато добавим ново устройство или ако надстроим старо устройство. Това спестява време и също така помага за поддържането на нашето основно ядро ​​без грешки. Полезно основно правило е, че не трябва да променяме нашето базово ядро, след като имаме работещо базово ядро. Също така помага при диагностицирането на системни проблеми. Например да предположим, че сме добавили модул към основното ядро ​​(т.е. сме модифицирали нашето основно ядро, като го прекомпилираме) и модулът има грешка в него. Това ще доведе до грешка при зареждане на системата и никога няма да разберем коя част от ядрото причинява проблеми. Докато ако заредим модула по време на изпълнение и той причини проблеми, веднага ще разберем проблема и можем да разтоварим модула, докато не го поправим. LKM са много гъвкави в смисъл, че могат да се зареждат и разтоварват с един команден ред. Това помага за спестяване на памет, тъй като зареждаме LKM само когато имаме нужда от тях. Освен това те не са по-бавни от основното ядро, защото извикването на едно от тях е просто зареждане на код от различна част от паметта. **Предупреждение: LKM не са потребителски космически програми. Те са част от ядрото. Те имат свободен ход на системата и лесно могат да я сринат. 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); 
Обяснение за горния код: Модулите на ядрото трябва да имат най-малко две функции: функция „старт“ (инициализация), наречена init_module(), която се извиква, когато модулът е включен в ядрото, и функция „край“ (почистване), наречена cleanup_module(), която се извиква точно преди да бъде rmmoded. Всъщност нещата се промениха, започвайки с ядрото 2.3.13. Вече можете да използвате каквото име искате за началната и крайната функция на модул. Всъщност новият метод е предпочитаният метод. Въпреки това много хора все още използват init_module() и cleanup_module() за своите начални и крайни функции. В този код сме използвали hello_start() като init функция и hello_end() като функция за почистване. Друго нещо, което може би сте забелязали е, че вместо функцията printf() сме използвали printk(). Това е така, защото модулът няма да отпечата нищо на конзолата, но ще регистрира съобщението в /var/log/kern.log. Следователно се използва за отстраняване на грешки в модули на ядрото. Освен това има осем възможни низа на ниво loglevel, дефинирани в заглавката, които са необходими при използване на printk(). Изброили сме ги в низходящ ред на тежест:
  • KERN_EMERG: Използва се за спешни съобщения, обикновено тези, които предхождат катастрофа.
  • KERN_ALERT: Ситуация, изискваща незабавно действие.
  • KERN_CRIT: Критични условия, често свързани със сериозни хардуерни или софтуерни повреди.
  • KERN_ERR: Използва се за съобщаване на условия за грешка; драйверите на устройства често използват KERN_ERR, за да докладват за хардуерни затруднения.
  • KERN_WARNING: Предупреждения за проблемни ситуации, които сами по себе си не създават сериозни проблеми със системата.
  • KERN_NOTICE: Ситуации, които са нормални, но все пак заслужават внимание. На това ниво се отчитат редица условия, свързани със сигурността.
  • KERN_INFO: Информационни съобщения. Много драйвери отпечатват информация за хардуера, който намират при стартиране на това ниво.
  • KERN_DEBUG: Използва се за съобщения за отстраняване на грешки.
  • Използвахме KERN_INFO, за да отпечатаме съобщението. Подготовка на системата за изпълнение на кода: 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 за компилиране на изходния код:
    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 
    **Забележка: Не забравяйте разделите в Makefile Компилиране и зареждане на модула: 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 
    Тестване на модула: 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.