如何将参数传递给Linux系统调用? [英] How to pass parameters to Linux system call?

查看:258
本文介绍了如何将参数传递给Linux系统调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名正在学习操作系统的大学生.

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
....

简介

  1. 我进行了简单的系统调用.

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆