在哪里可以找到Linux的syscall表?


13

我看到很多人在线参考

arch/x86/entry/syscalls/syscall_64.tbl

对于syscall表,效果很好。但很多其他参考

/include/uapi/asm-generic/unistd.h

通常在标头包中找到。怎么syscall_64.tbl显示

0 common  read      sys_read

正确的答案并unistd.h显示出来,

#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)

然后显示__NR_read

#define __NR_read 63
__SYSCALL(__NR_read, sys_read)

为什么是63,而不是1?我如何摆脱困境/include/uapi/asm-generic/unistd.h?仍然在/usr/include/asm/那里

/usr/include/asm/unistd_x32.h
#define __NR_read (__X32_SYSCALL_BIT + 0)
#define __NR_write (__X32_SYSCALL_BIT + 1)
#define __NR_open (__X32_SYSCALL_BIT + 2)
#define __NR_close (__X32_SYSCALL_BIT + 3)
#define __NR_stat (__X32_SYSCALL_BIT + 4)

/usr/include/asm/unistd_64.h
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4

/usr/include/asm/unistd_32.h
#define __NR_restart_syscall 0
#define __NR_exit 1           
#define __NR_fork 2           
#define __NR_read 3           
#define __NR_write 4          

有人可以告诉我这些unistd文件之间的区别。解释如何unistd.h运作?寻找系统调用表的最佳方法是什么?

Answers:


12

当我调查这种情况时,我发现直接询问编译器很有用(有关详细信息,请参阅在终端中打印标准C / GCC预定义宏):

printf SYS_read | gcc -include sys/syscall.h -E -

由此可见,涉及(在Debian)的标头是/usr/include/x86_64-linux-gnu/sys/syscall.h/usr/include/x86_64-linux-gnu/asm/unistd.h/usr/include/x86_64-linux-gnu/asm/unistd_64.h,和/usr/include/x86_64-linux-gnu/bits/syscall.h,并打印系统调用号码read,这是0上的x86-64。

如果安装了适当的系统头文件(在交叉编译器环境中),则可以找到其他体系结构的系统电话号码。对于32位x86,这非常简单:

printf SYS_read | gcc -include sys/syscall.h -m32 -E -

其中涉及/usr/include/asm/unistd_32.h其他头文件,并打印数字3。

因此,从用户空间角度来看,在中定义了32位x86系统调用,在中定义了asm/unistd_32.h64位x86系统调用asm/unistd_64.hasm/unistd_x32.h用于x32 ABI

uapi/asm-generic/unistd.h 列出默认的系统调用,这些默认系统调用用于没有特定于体系结构的系统调用表的体系结构。

在内核中,引用略有不同,并且是特定于体系结构的(同样,对于不使用通用系统调用表的体系结构)。这是诸如此类的文件arch/x86/entry/syscalls/syscall_64.tbl进入的地方(它们最终最终生成用于用户空间unistd_64.h等的头文件)。你会发现关于这个专题的对LWN文章的系统调用了很多更详细的,系统调用部分1的剖析系统调用第2部分的剖析


系统调用表在Linux内核版本和将来的内核版本之间稳定吗?
Biswapriyo

@Biswapriyo是,这是内核开发人员始终试图保留的ABI稳定性的一部分。新的系统调用,可以添加,但旧的不改,除了极少数极端情况下(如tux系统调用)。
斯蒂芬·基特


7

63 readarm64,0 readx86_64

每种体系结构的系统调用号都不同。

例如,arm64编号定义在:include/uapi/asm-generic/unistd.h显示63,另请参见:https ://reverseengineering.stackexchange.com/questions/16917/arm64-syscalls-table/18834#18834

如该答案中所述,我认为include / uapi / asm-generic / unistd.h是统一所有体系中系统调用号的较新尝试。

但是,由于无法更改系统调用号以不破坏系统调用API,因此在进行统一工作之前,较旧的架构已保留了这些旧编号。

这个问题要求一种自动的方法来获取完整的系统调用列表,包括参数:https : //stackoverflow.com/questions/6604007/how-can-i-get-a-list-of-linux-system-calls-and-自动获取的args数量

strace 源代码

我相信该工具,并且他们将数据保持整洁linux/,例如:

请注意,aarch64是我之前提到的#include不可知的arch 64/syscallent.h

这些表包含参数的数量,但不包含实际的参数类型,我想知道strace它们的编码位置。


3

此答案不会涉及的asm-generic版本unistd.h,因为没有包含它。1个

如中所述syscalls(2)

粗略地说,/usr/include/asm/unistd.h可以在例程sys_xxx()中的Linux内核源代码中找到属于系统调用的代码,其中定义的编号为__NR_xxx 。

也就是说,将在中找到正确的系统调用号/usr/include/asm/unistd.h。现在,在典型的x86系统上,这将仅包含一个asm/unistd_*.h文件,具体取决于目标。

适用于64位程序的syscall号位于中asm/unistd_64.h,适用于32位程序的syscall号asm/unistd_32.h(或几乎等效的_x32.h变体)。两者是不同的,因为32位和64位体系结构实际上是完全不同的操作系统。由于各种原因,它们共享相同的系统调用集,但顺序不同。

其中大多数还具有C语言包装器,因此很少需要syscall(2)直接使用。


1而且因为我不知道这是为了什么。


0

要添加所有出色的答案,有一个实用程序ausyscall可用于列出特定体系结构的所有syscall及其整数映射。

例如:

$ ausyscall --dump
Using x86_64 syscall table:
0   read
1   write
2   open
3   close
4   stat
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.