🕺作者: 主页
我的专栏 C语言从0到1 探秘C++ 数据结构从0到1 探秘Linux 😘欢迎关注:👍点赞🙌收藏??留言
🏇码字不易,你的👍点赞🙌收藏??关注对我真的很重要,有问题可在评论区提出,感谢支持!!!
在最新版本的 Linux 内核源代码中,系统调用入口表通常不再在 entry_64.S文件中。系统调用入口表的位置在不同的内核版本中可能会有所变化。通常,它会在 arch/x86/entry/syscalls/syscall_64.tbl
文件中定义。
新下载一个内核源代码,然后解压再进行下面步骤:
打开终端并进入内核源代码目录。根据内核版本,可能会有所不同:
cd /usr/src/linux-6.0.1 # 根据你的内核版本进入相应的目录
查找系统调用入口表的位置。可以使用以下命令找到它:
find . -name syscalls.h
这将在整个内核源代码目录中搜索 syscalls.h文件,如图所示。
vim ./arch/x86/include/asm/syscalls.h
图1 找到的syscalls.h 文件
打开找到的 syscalls.h
文件,在里面声明自己的系统调用函数,如图2所示。
图2打开syscalls.h文件
添加asmlinkage long sys_helloworld(void);
声明,如图3所示。
图3 添加声明
添加系统调用id:文件为 syscall_64.tbl
它包含系统调用号和系统调用函数之间的映射,如图4所示。
vim ./arch/x86/entry/syscalls/syscall_64.tbl
图4 添加系统调用
在文件中找到一个空的系统调用入口,通常为sys_ni_syscall
使用命令 /sys_ni_syscall 搜索,找到以后回车,然后 点击 i 即可修改
修改内容,如图5所示。:
图5 添加系统调用入口
这表示将系统调用号 156映射到名为 sys_my_call 的系统调用函数。
:wq
编写新的系统调用函数,先打开sys.c文件,如图6所示。
图6 打开sys.c文件
6. 在内核源代码目录中,打开文件 kernel/sys.c 以编辑,如图7所示。
图7 执行 vim kernel/sys.c命令
7. 在文件末尾添加你的新系统调用函数 sys_my_call的定义。例如,你可以添加一个简单的示例系统调用,如图8所示。
asmlinkage long sys_helloworld(void) {
printk(“hello world”);
return 1;
}
图8 添加系统调用
注意:这里函数定义部分有些教程中使用的是 asmlinkage helloworld(void)在高版本的内核中很可能会出现以下报错:
arch/x86/entry/syscall_64.o:(.rodata+0xa78):undefined reference to '__x64_sys_helloworld'
在我的版本下使用如下函数形式,如图9所示。
SYSCALL_DEFINE0(helloworld) {
Printk(“hello world!\n”);
return 0;
}
图9 添加系统调用
8. 保存文件并退出编辑器。
:wq
验证系统调用,如图14、15所示。
新建hello.c文件,编写程序如下:
#include <stdio.h>
#include<linux/kernel.h>
#include<sys/syscall.h>
#include<unistd.h>
int main()
{
long int a = syscall(156);
printf("System call sys_helloworld return %ld\n", a);
return 0;
}
图14 验证系统调用的代码
编译:
Gcc -o a hello.c
运行:
./a.out
图15 执行命令,验证系统调用添加成功
在本次实验中,我成功地增加了Linux系统调用,并通过重新编译内核和编写用户态程序的方式实现了对用户空间的读/写功能。在实验过程中,我遇到了以下一些问题和挑战:
存在问题:
注意事项:
有待提高的能力: