c - 如何给Linux系统调用传递参数?

标签 c linux linux-kernel parameter-passing system-calls

我是一名学习操作系统的大学生。

我正在尝试在 Linux 内核中添加我自己的系统调用,但出了点问题。

我的环境如下:

  • Linux 内核 v.4.19.1
  • 64 位 Ubuntu LTS 18.04.1,在 Oracle VirtualBox 5.2.18 上配备英特尔酷睿 i5-4210M CPU
  • 64 位 Windows 10 Home 1803 作为主机


因为我在 x86_64 机器上工作,所以我从 arch/x86/entry/syscalls/syscall_64.tbl 开始。 在 Linux 内核 v.4.19.1 中,最后一个条目是

334     common     rseq             __x64_sys_rseq

所以我在下面添加了这三行。

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 中添加了函数原型(prototype)。

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 并添加了函数的实现。

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

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-kpkgdpkg命令编译后,我做了一个测试程序。

#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
...
my_syscall_0
my_syscall_1 : 1111490392
my_syscall_2 : 1111490392, 1111490392

似乎每次执行程序时它都在变化。


显然,传递参数存在一些问题。但是,strace 命令向我显示值传递良好。

# strace ./syscall
...
syscall_0x14F(0x7ffd21866538, 0x7ffd21866548, ....) = 0
...
syscall_0x150(0x1, 0, 0, 0, 0x7f9e1562f3a0, ....) = 0
...
syscall_0x14F(0x2, 0x3, 0x7f9e1562f3a0, ....) = 0
....

简介

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

  2. 传递给它们的参数没有按应有的方式工作。

  3. 问题:为了增加新的系统调用,上面的步骤有没有问题?

  4. 问题:给系统调用传递参数有什么需要注意的问题吗?

提前致谢。

最佳答案

您需要告诉构建系统您的系统调用需要 2 个参数,并且它们是 int 类型。这样,作为构建系统一部分的脚本将生成适当的包装器,用于将参数转换为您需要的类型。您应该使用 -

而不是像您那样定义实际的处理程序
SYSCALL_DEFINE2(my_syscall_2, int, a, int, b) // Yes, there is a comma between the types and the argument names
{
    printk("my_syscall_2 : %d, %d\n", a, b);
    return b;
}

SYSCALL_DEFINExlinux/include/linux/syscalls.h 中定义.

您可以查看 linux/fs/read_write.c 中的示例

关于c - 如何给Linux系统调用传递参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53735886/

相关文章:

linux - 仅转储 linux 核心转储中的堆栈跟踪

c - 僵尸进程无法被杀死

Linux 上的 Java Runtime.exec() 参数

c - 如何在 Linux mint for windows 中编译 C GTK3+ 程序?

c - 如何将文件名的输入作为函数的参数?

c# - 从 C 调用 Mono exe 找不到 libc

c - C中未声明的标识符

c - libnl 出现错误 : Invalid Message

linux - 数据链路层库 linux 内核

c - 封装对类似结构的访问