摘要
本文讲述如何编写一个内核模块, 展示一个基本的编写内核模块的框架代码.
内核模块框架
示例源码
文件名: demoko.c
#include <linux/init.h>
#include <linux/module.h>
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debugging information");
#define dprintk(args...) \
if (debug) { \
printk(KERN_DEBUG args); \
}
static int mytest = 100;
module_param(mytest, int, 0644);
MODULE_PARM_DESC(mytest, "test for module parameter");
static int __init my_test_init(void)
{
dprintk("my first kernel module init\n");
dprintk("module parameter=%d\n", mytest);
return 0;
}
static void __exit my_test_exit(void)
{
printk("goodbye\n");
}
module_init(my_test_init);
module_exit(my_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mg");
MODULE_DESCRIPTION("kernel module parameter test");
MODULE_ALIAS("module parameter test");
源码解析
#include <linux/init.h> 这个包含了module_init()和module_exit()的函数声明.
#include <linux/module.h> 这个包含了文件底部的MODULE_LICENSE(), MODULE_AUTHOR等这些宏的声明.
module_init()宏告诉内核这是该模块的入口. 内核把所有模块的初始化函数都放在一个特别地段中来管理.
module_exit()宏告诉内核这是该模块的退出函数.
module_param()宏来实现模块参数的传递.
module_param(name, type, perm); name表示参数名, type表示参数类型, perm表示参数的读写等权限.
上述代码中, module_param(debug, int, 0644);的意思就是定一个参数叫debug, 它是int类型, 它的权限是0644.
模块参数会在sysfs中形成一个同名的文件, 即/sys/module/<moduel_name>/parameters/debug
可以读写这个文件. 写这个文件相当于向模块的debug参数传值.
MODULE_LICENSE()表示这个模块代码接受的软件许可协议.
MODULE_AUTHOR()用来描述这个模块的作者信息.
MODULE_DESCRIPTION()用来简单描述该模块的功能或用途, 也就是指定描述该模块的信息.
MODULE_ALIAS()为用户空间提供一个合适的别名.
编译构建
Makefile文件
BASEINCLUDE ?= /home/mg/workplace/code/gitee/runninglinuxkernel_4.0
#<module-name>-objs := <object-file>.o
myko-objs := demoko.o
# obj-m := <module-name>.o
obj-m := myko.o
all:
$(MAKE) -C $(BASEINCLUDE) M=$(PWD) modules;
clean:
$(MAKE) -C $(BASEINCLUDE) SUBDIRS=$(PWD) clean;
rm -f *.ko;
构建
[me@ukylin arm32]$ export ARCH=arm
[me@ukylin arm32]$ export CROSS_COMPILE=arm-linux-gnueabi-
[me@ukylin arm32]$ make
make -C /home/mg/workplace/code/gitee/runninglinuxkernel_4.0 M=/home/mg/workplace/rlk_basic/chapter4/arm32 modules;
make[1]: Entering directory '/home/mg/workplace/code/gitee/runninglinuxkernel_4.0'
CC [M] /home/mg/workplace/rlk_basic/chapter4/arm32/demoko.o
LD [M] /home/mg/workplace/rlk_basic/chapter4/arm32/myko.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/mg/workplace/rlk_basic/chapter4/arm32/myko.mod.o
LD [M] /home/mg/workplace/rlk_basic/chapter4/arm32/myko.ko
make[1]: Leaving directory '/home/mg/workplace/code/gitee/runninglinuxkernel_4.0'
[me@ukylin arm32]$
验证执行
/mnt # insmod myko.ko
[581396.688599] my first kernel module init
[581396.736305] module parameter=100
/mnt #
/mnt # cat /sys/module/myko/parameters/
debug mytest
/mnt # cat /sys/module/myko/parameters/debug
1
/mnt #
/mnt # cat /sys/module/myko/parameters/mytest
100
/mnt # echo 1000 > /sys/module/myko/parameters/mytest
/mnt #
/mnt # cat /sys/module/myko/parameters/mytest
1000
/mnt #