我阅读了 LKD 1中的一些段落, 但我无法理解以下内容:
从用户空间访问系统调用
通常,C 库提供对系统调用的支持。用户应用程序可以从标准头文件中提取函数原型并与 C 库链接以使用您的系统调用(或库例程,反过来,使用您的系统调用调用)。但是,如果您只是编写系统调用,那么 glibc 是否已经支持它是值得怀疑的!
值得庆幸的是,Linux 提供了一组宏来包装对系统调用的访问。它设置寄存器内容并发出陷阱指令。这些宏被命名为,其中0 到 6 之间。该数字对应于传递给系统调用的参数数量,因为宏需要知道预期有多少参数,因此需要推入寄存器。例如,考虑系统调用,定义为
_syscalln()
n
open()
long open(const char *filename, int flags, int mode)
在没有显式库支持的情况下使用此系统调用的系统调用宏将是
#define __NR_open 5 _syscall3(long, open, const char *, filename, int, flags, int, mode)
然后,应用程序可以简单地调用
open()
.对于每个宏,有 2+2×n 个参数。第一个参数对应于系统调用的返回类型。第二个是系统调用的名称。接下来按照系统调用的顺序为每个参数的类型和名称。
__NR_open
定义在<asm/unistd.h>
; 它是系统调用号。宏通过_syscall3
内联汇编扩展为 C 函数;程序集执行上一节中讨论的步骤,将系统调用号和参数推送到正确的寄存器中,并发出软件中断以陷入内核。将这个宏放在应用程序中是使用open()
系统调用所需的全部内容。让我们编写宏来使用我们出色的新
foo()
系统调用,然后编写一些测试代码来展示我们的努力。#define __NR_foo 283 __syscall0(long, foo) int main () { long stack_size; stack_size = foo (); printf ("The kernel stack size is %ld\n", stack_size); return 0; }
应用程序可以简单地调用open()
是什么意思?
此外,对于最后一段代码, 的声明在foo()
哪里?我怎样才能使这段代码可编译和可运行?我需要包含哪些头文件?
__________
1 Linux 内核开发,作者 Robert Love。
wordpress.com 上的 PDF 文件(转到第 81 页);谷歌图书搜索结果。