В этой статье речь пойдет о том, как создать модулья ядра Linux.
Так уже задуман Linux, что в нем есть пространство ядра (kernel-space) и пользователя (user-space). В пространстве пользователя выполняются все самые обычные программы, а вот взаимодействие с устройствами происходит при помощи кода, который выполняется из пространства ядра. Там же (в пространсве ядра) выполняется планировщик операционной системы и все служебные функции. Взаимодествие же программ из пространства пользователя с ядром происходит при помощи системных вызовов (system calls), но сейчас не о них, а о том, как создать простой модуль ядра.
Задачей данного модуля будет вывод строки hello world.
Ядро не может вывести строку нам в терминал. Зато оно может вывести её в лог (это делает функция printk). А мы позже его просмотрим при помощи утилиты dmesg.
Приступим.
Для того, чтобы собрать модуль нам понадобятся заголовки ядра. Установите пакет linux-headers / kernel-devel в зависимости от вашего дистрибутива. Это хорошо гуглится, поэтому не будем заострять внимание.
В любом модуле ядра Linux должно быть хотябы 2 функции. Точка входа й выхода.
Функция входа должна возвращать 0 в случа нормальной загрузки. После определения функций их нужно зарегистрировать.
Создайте файл blablamod.c:
#include <inux/init.h> #include <linux/module.h> #include "blablamod.h" static int __init blablamod_init( void ) { printk(KERN_NOTICE "BlablaModule loaded!\n" ); return 0; } static void __exit blablamod_exit( void ) { printk(KERN_NOTICE "BlablaModule unloaded!\n" ); } module_init( blablamod_init ); module_exit( blablamod_exit );
Файл blablamod.h:
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dmitrey Salnikov <mr.dimas@meta.ua>");
На этом программирование модуля заканчивается. Нам нужно его собрать. Для этого нужно создать Makefile.
KDIR = /lib/modules/$(shell uname -r)/build PWD = $(shell pwd) TARGET = blablamod obj-m := $(TARGET).o default: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: @rm -f *.o .*.cmd .*.flags *.mod.c *.order @rm -f .*.*.cmd *~ *.*~ TODO.* @rm -fR .tmp* @rm -rf .tmp_versions disclean: clean @rm *.ko *.symvers
Он в принципе не особо меняется. Шаблонный такой.
Можно собирать.
$ make make -C /lib/modules/3.19.0-rc2+/build M=/home/lamazavr/kernel_module/blablamod_01 modules make[1]: вход в каталог «/home/lamazavr/src/kernel/linux» CC [M] /home/lamazavr/kernel_module/blablamod_01/blablamod.o Building modules, stage 2. MODPOST 1 modules CC /home/lamazavr/kernel_module/blablamod_01/blablamod.mod.o LD [M] /home/lamazavr/kernel_module/blablamod_01/blablamod.ko make[1]: выход из каталога «/home/lamazavr/src/kernel/linux»
Теперь можно загружать модуль.
sudo insmod blablamod.ko
Можно проверять лог.
dmesg
В конце должно быть что-то вроде этого:
[ 544.652030] BlablaModule loaded!
Теперь выгружаем.
sudo rmmod blablamod
Опять проверяем лог. Видим там такое:
[ 640.847625] BlablaModule unloaded!
Ну и ради интереса проверим информацию о модуле.
modinfo blablamod.ko filename: /home/lamazavr/kernel_module/blablamod_01/blablamod.ko author: Dmitrey Salnikov <mr.dimas@meta.ua> license: GPL depends: vermagic: 3.19.0-rc2+ SMP mod_unload
Вот и все.
Весь код на github.