当我阅读有关系统调用的内容时,我搜索了“syscalls.h”以找到 LXR 中的头文件。搜索结果让我很困惑。有十几个“syscalls.h”文件来自“arch/_arch_name_/include/asm”下的目录。这些都可以,它们是架构特定的定义或其他需要的东西。问题是为什么我们在 /include/linux 和 /include/asm-generic 下有两个不同的“syscalls.h”头文件?
另外,我想找出 /include/linux 标头的用途以及 /include/asm-generic 标头的用途。他们如何区分彼此?拥有两个单独的标头文件夹背后的逻辑是什么?他们之间的关系如何?
谢谢
答案1
下面的标题asm/generic
主要是作为权宜之计,在编写特定于体系结构的版本之前,C 语言的可移植版本。您还会发现,在某些情况下,/usr/include/foobar.h
包含大量“内部实现”标头,最后依靠来自内核的部分(通常称为相同的部分)。示例是math.h
和 (更多依赖于 Linux)syscall.h
。
答案2
该软件必须是可移植的。如果您编译 C/C++ 源代码,那么您不需要知道您是否运行 i386/x86_64/arm/mips 或其他什么。标头以软件编译的方式链接。
所有其他头文件的存在是因为它们实现了许多不同的标准,有来自 BSD 的移植等等。其中许多都是有历史依据的。每个人从哪里来,为何存在,都有许多不同的原因,并且肯定会给出令人震惊的答案。
以及 asm-generic 的答案:堆栈溢出
答案3
arch/x86/entry/
有两个特殊的系统调用文件:
syscalls/syscall_32.tbl
和迪托“64”
系统调用很特殊,因为内核必须将 ABI 和 API 结合在一起。
一般来说,包含目录和其他头文件(独立的文件,如 kernel/sched/sched.h)遵循分层逻辑。我认为 make 和 gcc 都发挥了作用。
系统地使用这些符号来确保每个标头“单元”仅被读取一次。 (“保护性包装纸”,因为可能有太多的纵横交错)。这里来自include/linux/mm.h
:
#ifndef _LINUX_MM_H
#define _LINUX_MM_H
#include <linux/errno.h>
#ifdef __KERNEL__
... (#includes)
... (ext. decl. etc., the whole mm.h)
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
tbl 文件有:
# 32-bit system call numbers and entry vectors
该列表开头为:
0 i386 restart_syscall sys_restart_syscall __ia32_sys_restart_syscall
1 i386 exit sys_exit __ia32_sys_exit
2 i386 fork sys_fork __ia32_sys_fork
3 i386 read sys_read __ia32_sys_read
#
# 64-bit system call numbers and entry vectors
#
# The format is:
# <number> <abi> <name> <entry point>
#
# The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls
#
# The abi is "common", "64" or "x32" for this file.
稍后我会做布局...