网上找了一圈没有发现比较详细的(面向作业的教程),准备在这里分享一下实验过程。(命令行操作)
1.创建c文件和makefile文件
在任意位置创建一个文件夹(我创建的名称为/drive)
mkdir drive
后,
输入cd drive
进入文件夹。
输入vim hello.c
新建hello.c文件,输入以下代码
说明:
- 其中
printk()
函数是直接使用了向终端写函数tty_write() KERN_ALERT
代表打印级别,使之能够打印在终端上。
接下来编写makefile文件,输入 vim Makefile(注意首字母大写,否则编译过程中可能会报错)
,敲下以下代码:
这里需要说明:
- KERNELBUILD相当于一个自定义地址,指向的是你现在使用的Linux内核的源代码文件夹,我这里用的内核是
Linux 5.3.0-40
,而同一版本Linux的源码一般两个文件夹中(如下图),分为带后缀和不带后缀两种,这是为了保护Linux内核的源代码,我们这里选择带-geenric
后缀的文件名。 pwd
即为你当前工作的目录,它和KERNELBUILD共同构成Makefile的两个依赖。obj-m
指令的含义是表示该文件作为模块编译.
2.编译makefile文件
直接在/drive(我自己创建的文件夹)
下输入make
指令即可(只输入这一个单词)
关于出现“没有规则可以创建目标XXX”可能的原因:
- Makefile编写有问题
- 指向的文件夹不对
- Makefile首字母没大写。。。
编译之后我们可以看到出现了后缀为.ko
的文件,这就是我们要的模块
可以通过make clean
指令去除多余的中间文件
3.添加模块
直接通过指令insmod hello.ko
添加模块即可
安装后可以通过rmmod hello.ko
移除模块
可以通过指令dmesg |tail -1
查看是否添加成功
4.隐藏错误
通过指令dmesg |tail -1
查看模块是否添加成功时,遇到了以下报错
这是由于Linux内核3.7之后添加了内核签名机制,现在的内核只加载带有公钥的合法模块,因此可以尝试引入公钥mokutil --import public_key.der
:
但是我的电脑不支持。。
解决办法:
由于Linux中默认CONFIG_MODULE_SIG = y
即签名开启状态,因此可以在内核代码的config文件中找到并将其改为CONFIG_MODULE_SIG = n
。
当然也可以像我一样直接将这行代码加在Makefile末尾。
此时再通过dmesg |tail -1
指令:
成功!
//update 2020.2.27
喜欢别忘了点个赞呀