综述
添加系统调用的大致工作为:
- 下载Linux内核
- 在内核中添加调用
- 编译该更改后的内核
- 替换该内核并测试
准备工作
配置库
由于编译过程中需要很多库,因此需要提前进行配置。如果编译过程中遇到的报错均在下文的报错信息中记录。准备安装的库的命令为:
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install bison flex
sudo apt-get install libelf-dev libssl-dev
准备Linux内核
在https://www.kernel.org下载想要编译的Linux内核,为适应下述配置文件,笔者下载的是5.7.9版本。
将压缩包移至~
目录后,对文件进行解压,具体为:
xz -d linux-5.7.9.tar.xz
tar -xf linux-5.7.9.tar
下载WSL 2配置文件
由于是Linux内核针对WSL 2的编译替换过程,因此直接对内核进行编译将不能适应WSL 2的体系,导致不能正常启动,该直接编译内核的方法在文末也进行了记录。因此去下载相关配置文件,由于官方文件较老旧,因此去GitHub下载较新版本的,地址链接,该配置文件适应5.7.x内核。
将该文件命名为config-wsl
。在linux-5.7.9
文件夹下创建新的文件夹Microsoft
,并将config-wsl
移入文件夹Microsoft
中。
上述过程如下图:
添加函数
打开kernel/sys.c
文件,在末尾添加一个系统调用,如下:
SYSCALL_DEFINE0(hellolyg){
printk("Hello YigeLIU *_*");
return 1;
}
添加函数声明
打开include/linux/syscalls.h
文件,并在其中添加该函数声明,如下:
添加系统调用号
打开文件arch/x86/entry/syscalls/syscall_64.tbl
,在其中声明一个未使用的系统调用号。注意不可以在最后声明,因为该文件中有这样一段注释,如下:
这段注释的意思是:
32位系统特定的系统调用号从512开始,以避免对本机64位操作造成缓存影响。如果定义了X86_X32,则会为compat_sys_x*()兼容性系统调用动态创建__x32_compat_sys存根。
同时不能使用387至423号调用号,因为该文件中还有一段这样的注释,如下:
结合上述描述,将新调用号加至该段common后,如下:
编译内核与内核替换
该步骤与笔者文章WSL 2(Ubuntu18.04)编译Linux内核(5.7.9)并替换掉WSL 2原有内核中编译过程完全一致,不再赘述。编译结果如下:
对替换后的内核版本进行检查,观察到成功更新,如下:
测试系统调用
编写测试程序如下:
编译后使用dmesg
命令如下:
系统调用成功显示,如下:
一些可能的问题
由于笔者在编译过程中遇到了很多坎坷,且每次编译没有清空上次编译信息,因此最终编译通过不知道有没有因为以下原因,即起初修改kernel/sys.c
文件时,将添加的自定义系统调用函数定义为了:
参考资料
https://blog.csdn.net/xiaobai__lee/article/details/101979481
https://blog.csdn.net/qq_41175905/article/details/80529245