如何将参数传递给Linux系统调用? [英] How to pass parameters to Linux system call?
问题描述
我是一名正在学习操作系统的大学生.
I'm a college student studying OS.
我正在尝试在Linux内核中添加自己的系统调用,这出了问题.
I'm trying to add my own system call in Linux kernel, and something is going wrong.
我的环境如下:
- Linux内核v.4.19.1
- 在Oracle VirtualBox 5.2.18上具有Intel Core i5-4210M CPU的64位Ubuntu LTS 18.04.1
- 64位Windows 10 Home 1803作为主机
由于我在x86_64机器上工作,因此我从 arch/x86/entry/syscalls/syscall_64.tbl 开始.
在Linux内核v.4.19.1中,最后一个条目是
Since I'm working on x86_64 machine, I started with arch/x86/entry/syscalls/syscall_64.tbl.
In Linux kernel v.4.19.1, the last entry is
334 common rseq __x64_sys_rseq
所以我在下面添加了这三行.
so I added those three lines below it.
335 common my_syscall_0 sys_my_syscall_0
336 common my_syscall_1 sys_my_syscall_1
337 common my_syscall_2 sys_my_syscall_2
其次,我在 include/linux/syscalls.h 中添加了函数原型.
Second, I added prototypes of functions in include/linux/syscalls.h.
asmlinkage int sys_my_syscall_0(void);
asmlinkage int sys_my_syscall_1(int);
asmlinkage int sys_my_syscall_2(int, int);
第三,我创建了一个新文件 kernel/my_syscall.c 并添加了函数的实现.
Third, I created a new file kernel/my_syscall.c and added implementations of functions.
asmlinkage int sys_my_syscall_0(void)
{
printk("my_syscall_0\n");
return 0;
}
asmlinkage int sys_my_syscall_1(int a)
{
printk("my_syscall_1 : %d\n", a);
return 0;
}
asmlinkage int sys_my_syscall_0(int a, int b)
{
printk("my_syscall_2 : %d, %d\n", a, b);
return b;
}
然后,我在 kernel/Makefile 中添加了my_syscall.o来编译 kernel/my_syscall.c .
Then, I added my_syscall.o in kernel/Makefile to compile kernel/my_syscall.c as well.
obj-y = fork.o exec_domain.o panic.o \
cpu.o exit.o softirq.o resource.o \
sysctl.o sysctl_binary.o capability.o ptrace.o user.o \
signal.o sys.o umh.o workqueue.o pid.o task_work.o \
extable.o params.o \
kthread.o sys_ni.o nsproxy.o \
notifier.o ksysfs.o cred.o reboot.o \
async.o range.o smpboot.o ucount.o \
my_syscall.o
用 make-kpkg 和 dpkg 命令编译后,我制作了一个测试程序.
After compilation with make-kpkg and dpkg command, I made a test program.
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main()
{
printf("1 : %d\n", syscall(335));
printf("2 : %d\n", syscall(336, 1));
printf("3 : %d\n", syscall(337, 2, 3));
return 0;
}
但是,结果很奇怪. dmesg 向我展示了一些根本没有意义的数字.
However, the result is weird. dmesg shows me some huge numbers that does not make sense at all.
# dmesg
...
my_syscall_0
my_syscall_1 : 1111490392
my_syscall_2 : 1111490392, 1111490392
每次执行程序时似乎都在改变.
It seems like it is changing every time I execute the program.
显然,传递参数存在一些问题.但是, strace 命令告诉我这些值传递得很好.
Obviously, there's some problem in passing parameters. However, strace command shows me that the values are passed well.
# strace ./syscall
...
syscall_0x14F(0x7ffd21866538, 0x7ffd21866548, ....) = 0
...
syscall_0x150(0x1, 0, 0, 0, 0x7f9e1562f3a0, ....) = 0
...
syscall_0x14F(0x2, 0x3, 0x7f9e1562f3a0, ....) = 0
....
简介
-
我进行了简单的系统调用.
I made simple system calls.
向他们传递参数不能像应有的方式那样工作.
Passing parameter to them are not working as the way they should be.
问题:为了添加新的系统调用,上述步骤中是否存在任何问题?
Question : Is there any problem in steps above, in order to add new system call?
问题:将参数传递给系统调用时,我应该注意什么问题?
Question : Is there any issues that I should aware when passing parameters to system call?
先谢谢您.
推荐答案
我找到了解决方案.正如@Ajay Brahmakshatriya回答的那样,我应该使用SYSCALL_DEFINEx宏.而且,我也应该修改 arch/x86/entry/syscalls/syscall_64.tbl .
I found the solution. As @Ajay Brahmakshatriya answered, I should use SYSCALL_DEFINEx macro. And also, I should modify arch/x86/entry/syscalls/syscall_64.tbl as well.
这是最终摘要.
首先,修改 arch/x86/entry/syscalls/syscall_64.tbl :在下面添加这些行.
First, modify arch/x86/entry/syscalls/syscall_64.tbl : add those lines below.
335 common my_syscall_0 __x64_sys_my_syscall_0
336 common my_syscall_1 __x64_sys_my_syscall_1
337 common my_syscall_2 __x64_sys_my_syscall_2
第二,修改 include/linux/syscalls.h :在下面添加这些行.
Second, modify include/linux/syscalls.h : add those lines below.
asmlinkage long sys_my_syscall_0(void);
asmlinkage long sys_my_syscall_1(int);
asmlinkage long sys_my_syscall_2(int, int);
第三,创建一个新文件以进行实施.就我而言,是 kernel/my_syscall.c .
Third, create a new file for implementation. For my case, kernel/my_syscall.c.
#include <linux/syscalls.h>
#include <linux/kernel.h>
SYSCALL_DEFINE0(my_syscall_0)
{
printk("my_syscall_0\n");
return 0;
}
SYSCALL_DEFINE1(my_syscall_1, int, a)
{
printk("my_syscall_1 : %d\n", a);
return 0;
}
SYSCALL_DEFINE2(my_syscall_2, int, a, int, b)
{
printk("my_syscall_2 : %d, %d\n", a, b);
return b;
}
第四,将创建的文件添加到其目录中的Makefile中.就我而言,是内核/Makefile .
Fourth, add created file to Makefile in its directory. For my case, kernel/Makefile.
...
obj-y = fork.o exec_domain.o panic.o \
cpu.o exit.o softirq.o resource.o \
sysctl.o sysctl_binary.o capability.o ptrace.o user.o \
signal.o sys.o umh.o workqueue.o pid.o task_work.o \
extable.o params.o \
kthread.o sys_ni.o nsproxy.o \
notifier.o ksysfs.o cred.o reboot.o \
async.o range.o smpboot.o ucount.o \
my_syscall.o
...
最后,编译并安装内核.现在,您将可以看到新的系统调用运行良好.
Finally, compile and install the kernel. Now, you would be able to see new system calls working well.
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main()
{
printf("1 : %d\n", syscall(335));
printf("2 : %d\n", syscall(336, 1));
printf("3 : %d\n", syscall(337, 2, 3));
return 0;
}
dmesg 命令向我显示系统调用运行良好.
dmesg command shows me that system calls are working well.
# dmesg
my_syscall_0
my_syscall_1 : 1
my_syscall_2 : 2, 3
这篇关于如何将参数传递给Linux系统调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!