首先,您应该了解linux内核的作用,并且应用程序 仅
通过系统调用 才能 与内核交互。
实际上,应用程序在内核提供的“虚拟机”上运行:它在用户空间中运行,并且只能(在最低计算机级别上)执行用户CPU模式所允许的由指令(例如
SYSENTER或
INT0x80…)用于进行系统调用。因此,从用户级应用程序的角度来看,系统调用是原子的伪机器指令。
在Linux的大会HOWTO解释了如何一个系统调用可以在组件(即机器指令)的水平来完成。
的GNU库被提供对应于所述系统调用的C函数。因此,例如,开放函数是数字syscall上方的一小块胶水(即包装纸)
NR__open(它使syscall然后更新
errno)。应用程序通常在libc中调用此类C函数,而不是进行syscall。
您可以使用其他一些
libc。例如,MUSL libc非常“简单”,其代码也许更易于阅读。它还将原始系统调用包装到相应的C函数中。
如果添加自己的syscall,则最好也实现一个类似的C函数(在您自己的库中)。因此,您还应该为库提供一个头文件。
另请参见intro(2)和syscall(2)和syscalls(2)手册页,以及VDSO在syscalls中的作用。
请注意,系统调用不是C函数。他们不使用调用堆栈(甚至可以在没有任何堆栈的情况下调用它们)。syscall基本上是
NR__openfrom
的数字
<asm/unistd.h>,是一条
SYSENTER机器指令,约定
errno在C库包装中设置哪些寄存器在syscall的参数之前保留,哪些寄存器在syscall的结果(包括失败结果)之后保留。syscall)。syscall的约定不是ABI规范中C函数的调用约定(例如x86-64
psABI)。因此,您需要一个C包装器。



