添加一个新的系统调用
简介
添加一个获取cpu个数的系统调用,使用qemu测试
github
过程中产生的源码放到了这里
https://github.com/liodegwin/kernel/tree/main/syscall/add_a_syscall
参考
《linux内核设计与实现》第五章
https://huhaipeng.top/2019/04/20/linux%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8/
https://kernel.0voice.com/forum.php?mod=viewthread&tid=234
感谢/摄影
Photo by Pixabay: https://www.pexels.com/photo/ape-monkey-monkey-family-affchen-66865/
过程
注册系统调用号
需要在内核中添加新的系统调用号
位置
arch/x86/entry/syscalls/syscall_64.tbl
这里有提示
#don‘t usen umbers 387 through 423, add new calls after the last
#’common’entry
这表示不是所有的位置都能添加,注释中解释了有些数字是不能用的,选择一个能用的
我这里最后一个common的是448,因此我选择449,增加了一个新行,如下
1 | 449 common get_cpu_num sys_get_cpu_num |
声明系统调用函数
路径
/include/linux/syscalls.h中是所有的系统调用的接口,按照实现的源文件,都有注释,需要添加新的系统调用的接口,因为我打算把这个实现写在sys.c中,所以放到了相应的区域里面,其实放到很多的c文件中都可以。
新增加了一行,如下
1 | /*kernel/sys.c*/ |
添加实现
在很多源文件中都可以添加这个实现,我选择了kernel/sys.c
参照其他代码,添加了一个实现,如下
1 | SYSCALL_DEFINE0(get_cpu_number){ |
关于宏SYSCALL_DEFINE0,可以参考《linux内核设计与实现》5.6.2的内容
num_present_cpus则是一个内核中的宏,用来提供cpu数量
测试
编译内核
修改过三个文件之后,使用默认的配置编译内核得到bzImage
制作initramfs
在qemu中测试,编写测试代码,内容如下
1 | [liode@liodePC:159:qemufiles]$ cat test.c |
然后,要使用静态链接编译出可执行文件,放到initramfs的文件夹下,如果动态链接是找不到so文件的
1 | gcc -static test.c -o test |
最后将test放进入initramfs_d,制作出initramfs.img,启动qemu就可以了
其中Makefile等文件参见github中的内容
https://github.com/liodegwin/kernel/tree/main/syscall/add_a_syscall/qemufiles
最后的目录结构是这样的
1 | [liode@liodePC:160:qemufiles]$ tree |
运行qemu
修改makefile中的smp参数,该参数表示qemu硬件的cpu个数,可以得到不同的结果,当为2的时候qemu输出如下
1 | [ 2.113657] x86/mm: Checked W+X mappings: passed, no W+X pages found. |
添加系统调用成功