实现系统调用时,如何将系统调用号暴露给用户空间?
When implementing a system call, how do you expose the system call number to userland?
我正在摆弄系统调用。我添加了两个新的,并通过调用 syscall
.
来验证它们是否有效
我希望系统调用编号位于 header 中,这样用户空间就不必明确知道系统调用编号。
在 arch/x86/syscalls/syscall_64.tbl
我有:
317 64 krun_read_msrs sys_krun_read_msrs
318 64 krun_reset_msrs sys_krun_reset_msrs
一些 grepping 表明 kbuild 有 auto-generated 新系统调用的宏:
$ ag __NR_krun *
arch/x86/include/generated/uapi/asm/unistd_64.h
321:#define __NR_krun_read_msrs 317
322:#define __NR_krun_reset_msrs 318
文件名表明我不需要手动添加条目,但这与 Linux 内核文档所说的相反:
Some architectures (e.g. x86) have their own architecture-specific syscall tables, but several other architectures share a generic syscall table. Add your new system call to the generic list by adding an entry to the list in include/uapi/asm-generic/unistd.h:
#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)
好吧,我的系统调用是 x86_64 特定的,因为它们读取和写入仅在 Intel 芯片中发现的 MSR。所以在这之后,我开始挖掘,看看是否可以为我的 amd64 系统找到 arch-specific header。
您可能希望它在 arch/x86_64
之下,但其中根本没有包含。所以我假设 x86_64 继承自 x86
。既然如此,arch-specific header 应该是:
arch/x86/include/uapi/asm/unistd.h
如果你打开它,它只是一个基于 arch 的小包装器:
# ifdef __i386__
# include <asm/unistd_32.h>
# elif defined(__ILP32__)
# include <asm/unistd_x32.h>
# else
# include <asm/unistd_64.h>
# endif
所以这大概是为了获取 /usr/include/x86_64-linux-gnu/asm/unistd.h
而设计的,但这还不包括我的新系统调用编号。
我希望 headers_install
目标安装新的 headers(也许),但遗憾的是它没有。
我很困惑。我是否应该手动将新系统调用添加到文件中?如果是哪个文件?如果没有,我如何在标准位置将 auto-generated __NR_*
宏暴露给用户空间?
谢谢
好吧,我有一个部分答案。部分因为它是特定于 Debian 的。
如果您在内核源代码中使用 make deb-pkg
目标,则会在 parent 目录中创建 .deb
个包。如果您随后安装这些,那么您的 headers 就会安装到系统中。
在为我的内核执行上述操作后:
$ grep krun /usr/include
/usr/include/asm/unistd_64.h:#define __NR_krun_read_msrs 317
/usr/include/asm/unistd_64.h:#define __NR_krun_reset_msrs 318
内核构建过程分配的实际系统调用编号是内核构建过程的一部分...所以你不会得到实际的最终编号,但只能在一个已经构建的内核。构建您的内核,您将在构建的头文件中看到实际分配。恐怕您已经尝试在干净的内核源代码中搜索它们,这就是您找不到合适的包含文件的原因。
另一方面,隐藏实际的系统调用号是很常见的,它是由一些包含上述内核头文件的包装程序完成的,并使用 #define
d 符号来表示调用号进行 __SYSCAL(...)
实际调用。这通常甚至是必要的,因为每个系统调用通常都有不同的接口。您使用的所有正常系统调用都在 stdlib 中包含了它们的包装器,但新的不会包含在内。这里有两种方法:修补标准 C 库以包含(并在 /usr/include
中的某处为函数原型编写标准头文件) 或 以包含包装文件 mySysCall.o
(此名称方便您使用)在您要使用新系统调用的所有程序中。
我正在摆弄系统调用。我添加了两个新的,并通过调用 syscall
.
我希望系统调用编号位于 header 中,这样用户空间就不必明确知道系统调用编号。
在 arch/x86/syscalls/syscall_64.tbl
我有:
317 64 krun_read_msrs sys_krun_read_msrs
318 64 krun_reset_msrs sys_krun_reset_msrs
一些 grepping 表明 kbuild 有 auto-generated 新系统调用的宏:
$ ag __NR_krun *
arch/x86/include/generated/uapi/asm/unistd_64.h
321:#define __NR_krun_read_msrs 317
322:#define __NR_krun_reset_msrs 318
文件名表明我不需要手动添加条目,但这与 Linux 内核文档所说的相反:
Some architectures (e.g. x86) have their own architecture-specific syscall tables, but several other architectures share a generic syscall table. Add your new system call to the generic list by adding an entry to the list in include/uapi/asm-generic/unistd.h:
#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)
好吧,我的系统调用是 x86_64 特定的,因为它们读取和写入仅在 Intel 芯片中发现的 MSR。所以在这之后,我开始挖掘,看看是否可以为我的 amd64 系统找到 arch-specific header。
您可能希望它在 arch/x86_64
之下,但其中根本没有包含。所以我假设 x86_64 继承自 x86
。既然如此,arch-specific header 应该是:
arch/x86/include/uapi/asm/unistd.h
如果你打开它,它只是一个基于 arch 的小包装器:
# ifdef __i386__
# include <asm/unistd_32.h>
# elif defined(__ILP32__)
# include <asm/unistd_x32.h>
# else
# include <asm/unistd_64.h>
# endif
所以这大概是为了获取 /usr/include/x86_64-linux-gnu/asm/unistd.h
而设计的,但这还不包括我的新系统调用编号。
我希望 headers_install
目标安装新的 headers(也许),但遗憾的是它没有。
我很困惑。我是否应该手动将新系统调用添加到文件中?如果是哪个文件?如果没有,我如何在标准位置将 auto-generated __NR_*
宏暴露给用户空间?
谢谢
好吧,我有一个部分答案。部分因为它是特定于 Debian 的。
如果您在内核源代码中使用 make deb-pkg
目标,则会在 parent 目录中创建 .deb
个包。如果您随后安装这些,那么您的 headers 就会安装到系统中。
在为我的内核执行上述操作后:
$ grep krun /usr/include
/usr/include/asm/unistd_64.h:#define __NR_krun_read_msrs 317
/usr/include/asm/unistd_64.h:#define __NR_krun_reset_msrs 318
内核构建过程分配的实际系统调用编号是内核构建过程的一部分...所以你不会得到实际的最终编号,但只能在一个已经构建的内核。构建您的内核,您将在构建的头文件中看到实际分配。恐怕您已经尝试在干净的内核源代码中搜索它们,这就是您找不到合适的包含文件的原因。
另一方面,隐藏实际的系统调用号是很常见的,它是由一些包含上述内核头文件的包装程序完成的,并使用 #define
d 符号来表示调用号进行 __SYSCAL(...)
实际调用。这通常甚至是必要的,因为每个系统调用通常都有不同的接口。您使用的所有正常系统调用都在 stdlib 中包含了它们的包装器,但新的不会包含在内。这里有两种方法:修补标准 C 库以包含(并在 /usr/include
中的某处为函数原型编写标准头文件) 或 以包含包装文件 mySysCall.o
(此名称方便您使用)在您要使用新系统调用的所有程序中。