Manjaro下开发内核模块
linux采用模块化的思想来管理内核所提供的功能。比如驱动程序可以制作成模块,当安装上相应的硬件时,就将该模块载入,以提供访问该硬件的功能,当硬件被移除时,就将模块卸载,可以节约空间。
我使用Manjaro来作驱动开发,以下是我的经验。
一.编写一个简单的内核模块
参考LDD这本书,模块程序需要三个要素:
- 模块初始化函数
- 模块退出函数
- 模块所遵从的协议指定
上述三个要素组成一个最基本的模块程序,代码如下:
#include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h>
int __init test_init(void) { printk("test module hello wolrd"); return 0; } void __exit test_exit(void) { printk("test module bye bye"); } module_init(test_init); //用来声明模块初始化函数 module_exit(test_exit); //用来声明模块退出函数
MODULE_LICENSE("GPL"); //用来声明模块使用的协议
有了上述源代码,剩下的就是编写Makefile,我的如下:
obj-m := test_module.o PWD=$(shell pwd) BUILD="/lib/modules/5.4.18-1-MANJARO/build" all: make -C ${BUILD} M=$(PWD) modules clean: make -C ${BUILD} M=$(PWD) clean
Makefile的格式,在linux内核说明文档中有说明,具体路径为 ${KERNEL_PATH}/Documention/kbuild/modules.rst ,在该文档中就可以找到写一个内核模块的Makefile的格式。
二、装载 / 卸载内核模块及查看内核日志
1. modinfo
显示一个模块的信息
2. insmod
插入模块。这个命令执行时,模块被加载到内核空间中,且模块中的模块初始化函数(即使用module_init()指定的函数)将会被执行
3. rmmod
移除模块。这个命令执行时,模块被从内核空间中卸载,且模块中的模块退出函数(即使用module_exit()指定的函数)将会被执行
4.dmesg
打印内核日志
以我的模块test_module.ko为例, 在insmod和rmmod两个命令被执行时,都执行了printk函数,这个函数打印的内容都存放在内核日志中,使用dmesg命令可以查卡内核日志
多次装载卸载模块之后,可以看到内核日志中有多条test_module的注册退出函数打印的信息。
三.内核源码中的参考资料
比如在编写内核模块时,需要编写一个Makefile,如第一张展示的Makefile那样。
这个Makefile如何写,可以在相应版本的内核源码的Documents子目录中找到。具体的文件为 ${KERNEL}/Documentation/kbuild/modules.rst 。在较早版本的内核中,可能文件的扩展名是txt。
在Documentation/kbuild目录中,有很多关于内核构建系统kbuild的说明,可以参看。
Documentation/Changes文件,则描述了关于构建内核所需的gcc及其他工具的版本要求信息。