上QQ阅读APP看书,第一时间看更新
2.2 系统调用的包装函数
Linux 提供了所有或者说绝大多数进程所依赖的库函数,以为编写程序提供方便。
需要注意的是,与常规的函数调用不同,系统调用并不能被 C 语言之类的高级编程语言直接发起,只能通过与系统架构紧密相连的汇编语言代码来发起。例如,在 x86_64 架构中,是如下发起 getppid()
这个系统调用的6。
6第1 行的意思是,将 getppid
的系统调用编号 0x6e
传递给 eax
寄存器。这里的系统调用编号是由 Linux 预先定义好的。在第2 行中,通过 syscall
命令发起系统调用,并切换到内核模式。然后,开始执行负责处理 getppid
的内核代码。
mov $0x6e.%eax
syscall
平时没机会接触汇编语言的读者无须了解这些源代码的意义,抱着“这显然与平常见到的源代码完全不一样”这样的想法继续往下看就可以了。
如果没有 OS 的帮助,程序员就不得不根据系统架构为每一个系统调用编写相应的汇编语言代码,然后再从高级编程语言中调用这些代码(图 2-5)。
图 2-5 如果没有 OS 的帮助
这样一来,不但编写程序的时间增加了,程序也将无法移植到别的架构上。
为了解决这样的问题,OS 提供了一系列被称为系统调用的包装函数的函数,用于在系统内部发起系统调用。各种架构上都存在着对应的包装函数。因此,使用高级编程语言编写的用户程序,只需调用由高级编程语言提供的包装函数即可(图 2-6)。
图 2-6 用户程序只需调用包装函数即可