简介

添加一个获取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://garlicspace.com/2019/06/02/linux%E4%B8%8B%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8/

https://kernel.0voice.com/forum.php?mod=viewthread&tid=234

https://www.bilibili.com/video/BV12B4y1n7FF/?spm_id_from=333.788&vd_source=75dbec7ad4709dbb9145a059a5374980

感谢/摄影

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
2
/*kernel/sys.c*/
asmlinkage long sys_get_cpu_num(void);

添加实现

在很多源文件中都可以添加这个实现,我选择了kernel/sys.c

参照其他代码,添加了一个实现,如下

1
2
3
SYSCALL_DEFINE0(get_cpu_number){
return num_present_cpus();
}

关于宏SYSCALL_DEFINE0,可以参考《linux内核设计与实现》5.6.2的内容

num_present_cpus则是一个内核中的宏,用来提供cpu数量

测试

编译内核

修改过三个文件之后,使用默认的配置编译内核得到bzImage

制作initramfs

在qemu中测试,编写测试代码,内容如下

1
2
3
4
5
6
7
8
9
10
[liode@liodePC:159:qemufiles]$ cat test.c
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid = syscall(39);
printf("pid is %d\n",pid);
int cpu_num = syscall(449);
printf("syscall 449 ,cpu num is %d\n",cpu_num);
return 0;
}

然后,要使用静态链接编译出可执行文件,放到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
2
3
4
5
6
7
8
9
10
11
[liode@liodePC:160:qemufiles]$ tree
.
├── bzImage
├── initramfs_d
│ ├── bin
│ │ └── busybox
│ ├── init
│ └── test
├── initramfs.img
├── Makefile
└── test.c

运行qemu

修改makefile中的smp参数,该参数表示qemu硬件的cpu个数,可以得到不同的结果,当为2的时候qemu输出如下

1
2
3
4
5
6
7
8
9
10
[  2.113657] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[ 2.114042] rodata_test: all tests were successful
[ 2.114817] Run /init as init process
HelloToYou
sh: can't access tty; job control turned off
/ # [ 2.391701] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3

/ # ./test
pid is 146
syscall 449 ,cpu num is 2

添加系统调用成功