怎么开发内核模块
编译内核模块,依赖 linux-headers;
linux-headers 是什么?
linux-headers 是 linux 的开发头文件:
- linux-headers 系统正规路径在
/lib/modules/$(uname -r)
; - 如果是通过 apt-get 自行安装的 linux-headers 包(通常和内核镜像、新模块包一起安装),一般路径在
/usr/src/linux-headers-$(uname -r)
;
能开发内核模块的情况
- 开发本机内核模块:
- 可行情况一:存在 linux-headers(需要版本和本机内核版本匹配),一般虚拟机安装的 ubuntu 可以在
/lib/modules/$(uname -r)
找到; - 可行情况二:源码能编译当前版本的 kernel,配置好 .config 后,在内核目录执行
make scripts; make modules
就可以把该路径提供给其他模块进行编译了;
- 可行情况一:存在 linux-headers(需要版本和本机内核版本匹配),一般虚拟机安装的 ubuntu 可以在
- 开发小机端内核模块:需要有小机端 kernel,配置好 .config 后,在内核目录执行
make scripts; make modules
就可以把该路径提供给其他模块进行编译了;
WSL2 编译本地内核模块
由于 WSL2 没有相应的 linux-headers 文件,所以需要手动下载 wls2 的 linux kernel 源码;
下载 WSL2 kernel 源码
github 路径:Tags · microsoft/WSL2-Linux-Kernel · GitHub
我的 WSL2 内核版本是 5.10.16.3-microsoft-standard-WSL2,故下载 linux-msft-wsl-5.10.16.3;
1
2
3
4
5
6
# 下载到 ~/public
cd ~/public
wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.10.16.3.tar.gz
# 进行解压
tar -vxf WSL2-Linux-Kernel-linux-msft-wsl-5.10.16.3.tar.gz
编译一次源码中的模块
1
2
3
4
5
6
7
8
9
# 进入内核目录
cd WSL2-Linux-Kernel-linux-msft-wsl-5.10.16.3
# 更新配置
cp Microsoft/config-wsl .config
# 编译模块
make scripts
make modules
编写一个测试模块
测试模块 hello.ko
编写模块 hello.c:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <linux/module.h>
static int __init hello_init(void)
{
printk("Hello, Jerry!\n");
return 0;
}
static void __exit hello_exit(void)
{
printk("Goodbye, Jerry!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
对应 Makefile 如下:
1
2
3
4
5
6
7
8
9
obj-m:=hello.o
CURRENT_PATH:=$(shell pwd)
LINUX_KERNAL:=$(shell uname -r)
LINUX_KERNAL_PATH:=${HOME}/public/WSL2-Linux-Kernel-linux-msft-wsl-5.10.16.3
all:
make -C $(LINUX_KERNAL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNAL_PATH) M=$(CURRENT_PATH) clean
安装卸载 hello.ko 进行测试
1
2
3
4
5
# sudo insmod hello.ko 在 demsg 看到的效果
[60089.297242] Hello, Jerry!
# sudo rmmod hello.ko 在 demsg 看到的效果
[60178.271465] Goodbye, Jerry!