本期主题:
linux设备驱动之内核模块
往期链接:
0.开发环境
虚拟机ubuntu 16.04,内核版本为4.15(通过 $uname -r查看内核版本)
1.模块
1.1 模块定义
Linux内核整体架构非常庞大,其中包含的组件也非常多,我们是如何把需要的部分都包含在内核中的呢?有两种解决方案:
- 将所有的功能都编译到内核中,这样就会导致内核过于臃肿;
- 另外一种就是 内核本身并不包含我们想要的功能,通过动态加载的方式加载在内核中;
Linux内核提供了这样的机制,这种机制被称为模块(Module)
1.2 模块结构
一个Linux内核模块主要由以下几部分构成:
1.模块加载函数
通过 insmod或modprobe命令来加载内核模块,被加载的模块会自动被内核执行,完成本模块的初始化工作
2.模块卸载
通过rmmod命令卸载模块,与insmod相反
3.模块许可声明
许可证(LICENSE)描述内核模块的许可权限,一般使用MODULE_LICENSE(GPLv2)
4.模块参数/作者信息…(非必要参数)
1.3 简单例子
看一个打印hello的简单内核模块,module源码如下:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
static int hello_init(void)
{
printk("hello_init \n");
return 0;
}
static void hello_exit(void)
{
printk("hello_exit \n");
return;
}
module_init(hello_init); //insmod
module_exit(hello_exit);//rmmod
编译的Makefile
ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
else
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.symvers *.cmd *.mod.c *.order
endif
测试结果:
$ sudo dmesg -C #清除现有的所有信息
$ sudo insmod hello.ko
$ dmesg
[25648.391022] hello_init
$ sudo rmmod hello
$ dmesg
[25648.391022] hello_init
[25700.164221] hello_exit