📜  可加载内核模块 - Linux 设备驱动程序开发

📅  最后修改于: 2022-05-13 01:56:13.777000             🧑  作者: Mango

可加载内核模块 - 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);


图 1.1 Learn.c 文件

描述 :

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

图 1.2 一个简单的 Makefile

图 1.3 – 运行 make 命令后

图 1.4 – 在 Make 命令之后,我们看到生成了目标文件

第 3 步:insmod 和 rmmod

要加载模块,我们必须从源文件夹执行 insmod 命令。之后,驱动程序的名称被添加到 /proc/modules 文件中,而模块注册的设备被添加到 /proc/devices 文件中。然后我们需要使用 mknod /dev/simple-driver c 250 0 命令为我们的主编号创建特殊字符文件。创建设备文件后,我们需要执行最终验证以确保我们所做的工作按预期工作。为了验证,我们可以使用 cat 或 dmesg 查看 messages 命令来显示设备文件内容。

示例输出日志

1) 插入模块并查看消息

图 1.5 – 插入模块后的日志

2) 使用 rmmod 命令删除模块并调用退出函数

图 1.5 – 插入模块后的日志