一。内核动态模块介绍
Linux内核给开发者提供了灵活的模块加载方式,开发者可根据需要适当地选择静态或动态的方式将模块加入内核当中。静态加载的时候我们只需将驱动文件添加到对应的文件夹中并修改相应的Makefile和Kconfig即可,但是通过动态加载模块的方式,如果只是编译一个小的驱动文件而对内核大动干戈,那样编译的时间不仅长而且修改内核配置文件也是一件多余的工作。那么我们是否可以在不修改内核的前提下单独编译它是如何编译内核的呢?下面我们就通过分析它的Makefile入手简单介绍一个编译驱动(模块)文件的新方法。
动态模块生成文件后缀名为 *.ko
内核模块的相关操作
- 加载内核模块:insmod
- 卸载内核模块:rmmod
- 查看内核模块:lsmod
二。动态模块helloworld开发
本人习惯于使用开发工具强大的代码补全功能 觉得效率会更高 所以我这里使用clion开发 完成后拷贝到linux编译
clion开发环境配置
主要使用clion的提示 下载内核的源代码解压 找到include目录
接下来新建一个 c的库项目 里面有 CMakeLists.txt添加引入头文件
添加include_directories后 写代码依然是没有提示的 需要重新加载一个cmake Header Search PAths就有了新包含的头文件了
接下来新建一个hello.c 写代码就有提示拉 出错可以不管 反正window编译不了的
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static void hello_init(){
printk(KERN_INFO"***********hello world init");
}
static void hello_exit(){
printk(KERN_INFO"***********hello world exit");
}
module_init(hello_init);
module_exit(hello_exit);
拷贝到linux某个目录新建 Makefile(不能使用小写的makefile)
DIRS变量表示内核源代码的目录 一般安装的centos都没有 使用 yum -y install kernel-devel安装
如果uanme -r和源代码的版本号不对应 生成的ko是无法动态加载的
make -C 表示进入源代码目录编译 然后调用modules目标 传入一个参数M=当前目录 跳转到当前目录去make
obj-m:=hello.o表示当前生成的目标文件 会生成一个同名的hello.ko
obj-m := hello.o
DIRS :=/usr/src/kernels/3.10.0-862.14.4.el7.x86_64
all:
make -C $(DIRS) M=$(PWD) modules
clean:
rm -Rf *.o *.ko *.mod.c *.order *.symvers
执行make运行 查看是否生成hello.ko
加载(如果源代码和当前系统版本不匹配 是会出现下面错误)
[root@localhost kernel]# insmod hello.ko
insmod: ERROR: could not insert module hello.ko: Invalid module format
正确后可以使用
tail -f /var/log/messages查看是否正常打印了 加载初始化函数
[root@localhost kernel]# tail -20 /var/log/messages
Oct 18 16:34:09 localhost kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 05/19/2017
Oct 18 16:34:09 localhost kernel: Call Trace:
Oct 18 16:34:09 localhost kernel: [<ffffffff84d0d768>] dump_stack+0x19/0x1b
Oct 18 16:34:09 localhost kernel: [<ffffffff8470f5db>] load_module+0x275b/0x2bc0
Oct 18 16:34:09 localhost kernel: [<ffffffff849767a0>] ? ddebug_proc_write+0xf0/0xf0
Oct 18 16:34:09 localhost kernel: [<ffffffff8470b1e3>] ? copy_module_from_fd.isra.43+0x53/0x150
Oct 18 16:34:09 localhost kernel: [<ffffffff8470fbf6>] SyS_finit_module+0xa6/0xd0
Oct 18 16:34:09 localhost kernel: [<ffffffff84d1f7d5>] system_call_fastpath+0x1c/0x21
Oct 18 16:34:59 localhost kernel: ***********hello world exit
Oct 18 16:34:59 localhost kernel: ***********hello world init
接下来可以使用 rmmod删除模块 可以使用lsmod显示所有加载的模块