可加载内核模块 - Linux 设备驱动程序开发
对于 Linux 设备驱动程序,我们只能使用两种语言:Assembler 和 C。Assembler 实现了 Linux 内核的主要部分,而 C 实现了与体系结构相关的部分。上传的内核模块通常被称为内核模块或模块,但这些名称具有误导性,因为世界上有这么多类型的模块,而内置在基本内核中的各个部分很容易被称为模块。对于 HOWTO 所指的某些类型的模块,我们使用术语内核模块或 LKM。有些人认为 LKM 在内核之外。他们谈论连接到内核的 LKM。这是个错误; LKM(如果已加载)是内核的很大一部分。与您正在启动的映像相关的内核部分(即除 LKM 之外的整个内核)的正确术语是“基本内核”。 LKM 连接到基本内核。让我们开始使用常青启动程序——“Hello -World”为 Linux 编写可加载内核模块。
要了解有关可加载内核模块的更多信息,请访问 linux 可加载内核模块
第 1 步:编写代码
示例文件:学习。 C
C
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_VERSION("4.15.0-133-generic");
static int __init start(void)
{
printk(KERN_INFO "Loading module....");
printk(KERN_INFO "Hello World....");
return 0;
}
static void __exit end(void)
{
printk(KERN_INFO "Bye World....");
}
module_init(start);
module_exit(end);
描述 :
my_init函数是驱动程序初始化入口点,在系统启动期间(如果驱动程序被静态编译到内核中)或模块插入内核时调用。 my_exit函数是驱动程序退出点。从 Linux 内核卸载模块时调用它。如果驱动程序被静态编译到内核中,则此函数无效。这些函数在 linux/module.h 头文件中声明。
第 2 步:构建内核模块
在现代内核版本中,Makefile 负责为开发人员构建大部分内容。它启动内核构建系统并提供构建模块所需的组件列表。我们提供内核版本的构建路径,它会生成 .ko 和其他文件。生成的此内核对象 (KO) 文件不会加载到内核中。
示例 MakeFile
obj-m += learn.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
第 3 步:insmod 和 rmmod
要加载模块,我们必须从源文件夹执行 insmod 命令。之后,驱动程序的名称被添加到 /proc/modules 文件中,而模块注册的设备被添加到 /proc/devices 文件中。然后我们需要使用 mknod /dev/simple-driver c 250 0 命令为我们的主编号创建特殊字符文件。创建设备文件后,我们需要执行最终验证以确保我们所做的工作按预期工作。为了验证,我们可以使用 cat 或 dmesg 查看 messages 命令来显示设备文件内容。
示例输出日志
1) 插入模块并查看消息
ubuntu@ubuntu:~/Desktop/LKM$ sudo insmod learn.ko
ubuntu@ubuntu:~/Desktop/LKM$ dmesg | tail -10
[ 1179.315828] audit: type=1400 audit(1645410095.127:35): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.hook.configure” pid=4520 comm=”apparmor_parser”
[ 1181.044041] audit: type=1400 audit(1645410096.856:36): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.snap-store” pid=4521 comm=”apparmor_parser”
[ 1182.803700] audit: type=1400 audit(1645410098.616:37): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software” pid=4522 comm=”apparmor_parser”
[ 1184.677654] audit: type=1400 audit(1645410100.492:38): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software-local-file” pid=4526 comm=”apparmor_parser”
[ 1282.734538] rfkill: input handler disabled
[ 5315.486562] learn: module verification failed: signature and/or required key missing – tainting kernel
[ 5315.486700] Loading module….
[ 5315.486702] Hello World….
2) 使用 rmmod 命令删除模块并调用退出函数
ubuntu@ubuntu:~/Desktop/LKM$ sudo rmmod learn
ubuntu@ubuntu:~/Desktop/LKM$ dmesg | tail -10
[ 1181.044041] audit: type=1400 audit(1645410096.856:36): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.snap-store” pid=4521 comm=”apparmor_parser”
[ 1182.803700] audit: type=1400 audit(1645410098.616:37): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software” pid=4522 comm=”apparmor_parser”
[ 1184.677654] audit: type=1400 audit(1645410100.492:38): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software-local-file” pid=4526 comm=”apparmor_parser”
[ 1282.734538] rfkill: input handler disabled [ 5315.486562] learn: module verification failed: signature and/or required key missing – tainting kernel
[ 5315.486700] Loading module….
[ 5315.486702] Hello World….
[ 5340.195459] Bye World….