哪个系统调用号的头文件是正确的?
Which header file of system call numbers is correct?
我最近在做一些内核编码,我发现了 2 个 unistd.h
文件。
第一个的位置是/usr/include/asm/unistd.h
。第二个来自内核的源代码:linux/include/uapi/asm-generic/unistd.h
。
源代码的版本和我的内核是一样的,但是两个头文件
各不相同。
/usr/include/asm/unistd.h
(来自我的电脑):
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
linux/include/uapi/asm-generic/unistd.h
(来源:
#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
#define __NR_io_destroy 1
__SYSCALL(__NR_io_destroy, sys_io_destroy)
#define __NR_io_submit 2
__SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
#define __NR_io_cancel 3
__SYSCALL(__NR_io_cancel, sys_io_cancel)
#define __NR_io_getevents 4
__SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents)
/* fs/xattr.c */
#define __NR_setxattr 5
__SYSCALL(__NR_setxattr, sys_setxattr)
#define __NR_lsetxattr 6
__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
#define __NR_fsetxattr 7
__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
#define __NR_getxattr 8
__SYSCALL(__NR_getxattr, sys_getxattr)
#define __NR_lgetxattr 9
有什么区别?我应该使用哪一个来索引 sys_call_table
?
asm-generic
一个是模板版本,如果您正在为内核开发新的体系结构,则可以使用它。我相信您会发现内核源代码中实际上有很多版本的 unistd.h
,因为系统调用的顺序(以及系统调用的存在)因体系结构而异。从内核源代码层次结构的根目录开始尝试:
find . -name 'unistd*.h'
对于 x86,uapi
版本是在您构建内核时 生成的 。请参阅 Makefile
和 arch/x86/entry/syscalls/
目录中的各种 *.tbl
文件。这最终会生成文件:
arch/x86/include/generated/uapi/asm/unistd_64.h
arch/x86/include/generated/uapi/asm/unistd_32.h
arch/x86/include/generated/uapi/asm/unistd_x32.h
(所有这些都是 #include
d 来自存根 unistd.h
文件)。
最终 linux "distro" 的创建非常 architecture-specific,因此由发行版创建者将正确的 unistd.h
文件复制到一些/usr/include
层次结构中的适当位置。 (当然,您的 libc
也需要针对正确的版本进行编译,以便普通的 libc
系统调用能够正常工作。)
总而言之,/usr/include/asm
中的版本更好 匹配您的 运行 内核,否则将无法正确生成 ad-hoc 来自系统上用户进程的系统调用,但是你 不应该 在内核源代码层次结构中使用那个,因为内核源代码层次结构绝对不依赖于用户 space headers。在内核源代码中,table 的索引机制是 architecture-dependent,因为 table 的布局和顺序本身就是 architecture-dependent,并且只有 architecture-specific 代码(系统调用入口代码)通常访问 table,因此只有该代码 "needs to know" 是正确的索引。
现在,如果您正在创建一个新的系统调用,您需要在所有 unistd.h
文件中为您希望它出现的所有体系结构定义它的编号。
这实际上取决于您要寻找的体系结构。这从一个拱形到另一个拱形变化,通常放在 arch/$ARCH
文件夹下的某个地方。对于嵌入式架构,这通常是硬编码 table,甚至可能会因不同的变体而改变。
对于 x86/64,此 table 是在构建时自动生成的,如您在 arch/x86/Makefile
中所见
syscall32 := $(srctree)/$(src)/syscall_32.tbl
syscall64 := $(srctree)/$(src)/syscall_64.tbl
...
$(uapi)/unistd_32.h: $(syscall32) $(syshdr)
$(call if_changed,syshdr)
...
$(uapi)/unistd_64.h: $(syscall64) $(syshdr)
$(call if_changed,syshdr)
这基本上调用了 arch/x86/entry/syscalls/syscallhdr.sh
脚本,该脚本将根据您的 menuconfig
.[=19 自动生成您的 unistd_32.h
/unistd_x32.h
/unistd_64.h
文件=]
这意味着,如果您要查找 x86/x64 的实际系统调用 table,可以在此处找到它们:
arch/x86/entry/syscalls/syscall_32.tbl
/arch/x86/entry/syscalls/syscall_64.tbl
我最近在做一些内核编码,我发现了 2 个 unistd.h
文件。
第一个的位置是/usr/include/asm/unistd.h
。第二个来自内核的源代码:linux/include/uapi/asm-generic/unistd.h
。
源代码的版本和我的内核是一样的,但是两个头文件
各不相同。
/usr/include/asm/unistd.h
(来自我的电脑):
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
linux/include/uapi/asm-generic/unistd.h
(来源:
#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
#define __NR_io_destroy 1
__SYSCALL(__NR_io_destroy, sys_io_destroy)
#define __NR_io_submit 2
__SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
#define __NR_io_cancel 3
__SYSCALL(__NR_io_cancel, sys_io_cancel)
#define __NR_io_getevents 4
__SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents)
/* fs/xattr.c */
#define __NR_setxattr 5
__SYSCALL(__NR_setxattr, sys_setxattr)
#define __NR_lsetxattr 6
__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
#define __NR_fsetxattr 7
__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
#define __NR_getxattr 8
__SYSCALL(__NR_getxattr, sys_getxattr)
#define __NR_lgetxattr 9
有什么区别?我应该使用哪一个来索引 sys_call_table
?
asm-generic
一个是模板版本,如果您正在为内核开发新的体系结构,则可以使用它。我相信您会发现内核源代码中实际上有很多版本的 unistd.h
,因为系统调用的顺序(以及系统调用的存在)因体系结构而异。从内核源代码层次结构的根目录开始尝试:
find . -name 'unistd*.h'
对于 x86,uapi
版本是在您构建内核时 生成的 。请参阅 Makefile
和 arch/x86/entry/syscalls/
目录中的各种 *.tbl
文件。这最终会生成文件:
arch/x86/include/generated/uapi/asm/unistd_64.h
arch/x86/include/generated/uapi/asm/unistd_32.h
arch/x86/include/generated/uapi/asm/unistd_x32.h
(所有这些都是 #include
d 来自存根 unistd.h
文件)。
最终 linux "distro" 的创建非常 architecture-specific,因此由发行版创建者将正确的 unistd.h
文件复制到一些/usr/include
层次结构中的适当位置。 (当然,您的 libc
也需要针对正确的版本进行编译,以便普通的 libc
系统调用能够正常工作。)
总而言之,/usr/include/asm
中的版本更好 匹配您的 运行 内核,否则将无法正确生成 ad-hoc 来自系统上用户进程的系统调用,但是你 不应该 在内核源代码层次结构中使用那个,因为内核源代码层次结构绝对不依赖于用户 space headers。在内核源代码中,table 的索引机制是 architecture-dependent,因为 table 的布局和顺序本身就是 architecture-dependent,并且只有 architecture-specific 代码(系统调用入口代码)通常访问 table,因此只有该代码 "needs to know" 是正确的索引。
现在,如果您正在创建一个新的系统调用,您需要在所有 unistd.h
文件中为您希望它出现的所有体系结构定义它的编号。
这实际上取决于您要寻找的体系结构。这从一个拱形到另一个拱形变化,通常放在 arch/$ARCH
文件夹下的某个地方。对于嵌入式架构,这通常是硬编码 table,甚至可能会因不同的变体而改变。
对于 x86/64,此 table 是在构建时自动生成的,如您在 arch/x86/Makefile
中所见syscall32 := $(srctree)/$(src)/syscall_32.tbl
syscall64 := $(srctree)/$(src)/syscall_64.tbl
...
$(uapi)/unistd_32.h: $(syscall32) $(syshdr)
$(call if_changed,syshdr)
...
$(uapi)/unistd_64.h: $(syscall64) $(syshdr)
$(call if_changed,syshdr)
这基本上调用了 arch/x86/entry/syscalls/syscallhdr.sh
脚本,该脚本将根据您的 menuconfig
.[=19 自动生成您的 unistd_32.h
/unistd_x32.h
/unistd_64.h
文件=]
这意味着,如果您要查找 x86/x64 的实际系统调用 table,可以在此处找到它们:
arch/x86/entry/syscalls/syscall_32.tbl
/arch/x86/entry/syscalls/syscall_64.tbl