千峰视频 内核模块编写流程module_init,module_exit,MODULE_LICENSE 最简单的内核模块编写
1
doc@[toc]
模块编写的流程,先在pc上测试
pc也是linux内核。
内核提供的三个宏,module_init,module_exit,MODULE_LICENSE
前俩在include/linux/init.h
中定义,MODULE_LICENSE在include/linux/module.h
中定义,
入口出口和GPL协议说明都是宏函数。
0. 入出口函数,GPL声明
在内核源码中找到一个入出口函数,
static int __init omap2_mbox_init(void)
{
return platform_driver_register(&omap2_mbox_driver);
}
static void __exit omap2_mbox_exit(void)
{
platform_driver_unregister(&omap2_mbox_driver);
}
module_init(omap2_mbox_init);
module_exit(omap2_mbox_exit);
MODULE_LICENSE("GPL");
大致结构如下:
__init将函数统一放在__init段,入口函数参数为void,返回值为int,用__init修改函数属性,
__exit将函数统一放在__exit段,出口函数参数为void,返回值为void,用__exit修改函数属性,
将入出口函数指针传入
static int __init xxx_init(void)
{
return platform_driver_register(&omap2_mbox_driver);
}
static void __exit xxx_exit(void)
{
platform_driver_unregister(&omap2_mbox_driver);
}
module_init(xxx_init);
module_exit(xxx_exit);
MODULE_LICENSE("GPL");
1. 编写内核模块
至少包含那三个宏函数。
查看当前ubuntu系统的linux内核版本号,name -r
ubuntu的linux内核在/lib/modules/5.0.0-37-generic/build
,init.h在/lib/modules/5.0.0-37-generic/build/include/linux
下。
编写内核模块,就打印个信息:
#include <linux/init.h>
#include <linux/module.h>
int __init module_demo_init(void)
{
printk("-----%s-----%s-----%d", __FILE__, __func__, __LINE__);
return 0;
}
void __exit module_demo_exit(void)
{
printk("-----%s-----%s-----%d", __FILE__, __func__, __LINE__);
}
module_init(module_demo_init);
module_exit(module_demo_exit);
MODULE_LICENSE("GPL");
2. 编译内核模块
- 静态编译
编译到uImage中 - 动态编译
编译生成动态模块.ko
外部编译内核模块时,在Documentation/kbuild/modules.txt中有说明,
make -C <path-to-kernel> M=`pwd` # -C到指定路径下执行Makefile,内核源码路径,M表示外部模块所处路径,编译目标
...
make -C /lib/modules/`uname -r`/build M=`pwd`
Makefile内容如下:
KERNDIR := /lib/modules/5.0.0-37-generic/build/ # 系统内核的路径
PWD := $(shell pwd) # 执行pwd命令并把结果赋给PWD
obj-m := module_demo.o # .ko的生成依赖于.o,.o默认依赖.c
all:
make -C $(KERNDIR) M=$(PWD) modules # modules为编译目标
clean:
nake -C $(KERNDIR) M=$(PWD) clean
make
后在内核模块路径(当前路径下)生成module_demo.ko
文件,这个文件由pc对应的编译器编译生成,所以可以插入到pc内核中运行。
3. 使用内核模块
将内核模块加入到内核中,与内核形成整体,然后运行。
也可以从内核模块中卸载内核 内核模块。
3.1 内核模块信息
查看内核模块信息:modinfo
, 如modinfo module_demo.ko
,
当然还可以包含作者,模块描述等信息,需要添加其他宏函数,在include/linux/module.h中定义,
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
/* Author, ideally of form NAME[, NAME]*[ and NAME] */
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
/* What your module does. */
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
3.2 查看当前系统插入的动态内核模块
lsmod
3.3 插入内核模块
需要管理员权限
insmod module_demo.ko
# 加载函数会被调用
3.4 查看内核日志信息
dmesg
可以先删除之前的内核日志sudo dmesg -c
3.5 卸载内核模块
sudo rmmod module_demo
# 卸载函数会被调用
最终可以看到写的module_demo.ko内核模块在pc内核中运行的结果,
内核模块 加载的时候 执行加载函数,只执行一次,
内核模块 卸载的时候 执行卸载函数,只执行一次。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)