Модули кернела су делови кода који се могу учитати и учитати у кернел на захтев. Они проширују функционалност кернела без потребе за поновним покретањем система. Прилагођени кодови се могу додати Линук кернелима на два начина. - Основни начин је додавање кода изворном стаблу кернела и поновно компајлирање кернела.
- Ефикаснији начин је да се то уради додавањем кода у кернел док је покренут. Овај процес се зове учитавање модула где се модул односи на код који желимо да додамо језгру.
Пошто ове кодове учитавамо током извршавања и они нису део званичног Линук кернела, они се називају модул језгра који се може учитати (ЛКМ) који се разликује од основног кернела. Основно језгро се налази у директоријуму /боот и увек се учитава када покренемо нашу машину, док се ЛКМ-ови учитавају након што је основно језгро већ учитано. Без обзира на то, ови ЛКМ су у великој мери део нашег кернела и комуницирају са основним језгром да би завршили своје функције. ЛКМ-ови могу да обављају различите задатке, али у основи спадају у три главне категорије - драјвер уређаја
- драјвер система датотека и
- Системски позиви.
Коју предност нуде ЛКМ? Једна од главних предности коју имају је да не морамо да обнављамо кернел сваки пут када додамо нови уређај или ако надоградимо стари уређај. Ово штеди време и такође помаже да наше основно језгро остане без грешака. Корисно правило је да не треба да мењамо наше основно језгро када имамо функционално основно језгро. Такође помаже у дијагностицирању системских проблема. На пример, претпоставимо да смо додали модул основном језгру (тј. модификовали смо наше основно језгро тако што смо га поново компајлирали) и да модул има грешку у себи. Ово ће узроковати грешку при покретању система и никада нећемо знати који део кернела изазива проблеме. Док ако учитамо модул у току извршавања и изазове проблеме, одмах ћемо сазнати за проблем и можемо уклонити модул док га не поправимо. ЛКМ-ови су веома флексибилни у смислу да се могу учитати и испразнити једном линијом команде. Ово помаже у уштеди меморије јер учитавамо ЛКМ само када су нам потребни. Штавише, они нису спорији од основног кернела јер позивање било којег од њих једноставно учитава код из другог дела меморије. **Упозорење: ЛКМ-ови нису кориснички просторни програми. Они су део језгра. Они имају слободан рад система и лако га могу срушити. 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);
Објашњење за горњи код: Модули кернела морају имати најмање две функције: функцију 'старт' (иницијализацију) која се зове инит_модуле() која се позива када се модул убаци у језгро и 'енд' (чишћење) функцију која се зове цлеануп_модуле() која се позива непосредно пре него што је рммодед. У ствари, ствари су се промениле почевши од кернела 2.3.13. Сада можете користити било које име за почетну и крајњу функцију модула. У ствари, нова метода је пожељна метода. Међутим, многи људи и даље користе инит_модуле() и цлеануп_модуле() за своје почетне и крајње функције. У овом коду смо користили хелло_старт() као инит функцију и хелло_енд() као функцију чишћења. Још једна ствар коју сте можда приметили је да смо уместо функције принтф() користили принтк(). То је зато што модул неће штампати ништа на конзоли, али ће пријавити поруку у /вар/лог/керн.лог. Због тога се користи за отклањање грешака у модулима кернела. Штавише, постоји осам могућих стрингова на нивоу дневника дефинисаних у заглављу који су потребни док се користи принтк(). Навели смо их по опадајућој озбиљности: - КЕРН_ЕМЕРГ: Користи се за хитне поруке, обично оне које претходе паду.
- КЕРН_АЛЕРТ: Ситуација која захтева хитну акцију.
- КЕРН_ЦРИТ: Критични услови често повезани са озбиљним кваровима хардвера или софтвера.
- КЕРН_ЕРР: Користи се за пријављивање стања грешке; драјвери уређаја често користе КЕРН_ЕРР да пријаве хардверске потешкоће.
- КЕРН_ВАРНИНГ: Упозорења о проблематичним ситуацијама које саме по себи не стварају озбиљне проблеме са системом.
- КЕРН_НОТИЦЕ: Ситуације које су нормалне, али ипак вредне пажње. Бројни безбедносни услови су пријављени на овом нивоу.
- КЕРН_ИНФО: Информативне поруке. Многи управљачки програми штампају информације о хардверу који пронађу у тренутку покретања на овом нивоу.
- КЕРН_ДЕБУГ: Користи се за отклањање грешака у порукама.
Користили смо КЕРН_ИНФО за штампање поруке. Припрема система за покретање кода: 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)
Макефиле за компајлирање изворног кода: 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
**Напомена: Не заборавите размаке на картици у Макефиле-у Састављање и учитавање модула: 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.