什么是系统调用,系统调用的过程
系统调用(system call)提供操作系统服务接口。这些调用通常以 C 或 C++ 编写,当然,对某些底层任务(如需直接访问硬件的任务),可能应以汇编语言指令编写。 注意,除非特别说明,贯穿本书的系统调用名称为通用的。每个操作系统对于每个系统调用都有自己的名称。 在后台,API 函数通常为应用程序员调用实际的系统调用。例如,Windows 函数 Create-Process()(显然用于创建一个新进程)实际调用 Windows 内核的系统调用 NTCreateProcess()。为什么应用程序员更喜欢根据 API 来编程,而不是采用实际系统调用呢?这么做有多个原因。 一个好处涉及程序的可移植性。应用程序员根据 API 设计程序,以希望程序能在任何支持同一 API 的系统上编译并执行(虽然在现实中体系差异往往使这一点更困难)。再者,对应用程序员而言,实际系统调用比 API 更为注重细节且更加难用。尽管如此,在 API 的函数和内核中的相关系统调用之间常常还是存在紧密联系的。事实上,许多 POSIX 和 Windows 的 API 还是类似于 UNIX、Linux 和 Windows 操作系统提供的系统调用。 对大多数的程序设计语言,运行时支持系统(由编译器直接提供的函数库)提供了系统调用接口(system-call interface),以链接到操作系统的系统调用。系统调用接口截取 API 函数的调用,并调用操作系统中的所需系统调用。通常,每个系统调用都有一个相关数字,而系统调用接口会根据这些数字来建立一个索引列表。系统调用接口就可调用操作系统内核中的所需系统调用,并返回系统调用状态与任何返回值。 调用者无需知道如何实现系统调用,而只需遵循 API,并知道在调用系统调用后操作系统做了什么。因此,通过 API,操作系统接口的大多数细节可隐藏起来,且可由运行时库来管理。API、系统调用接口和操作系统之间的关系如图 2 所示,它说明在用户应用程序调用了系统调用 open() 后,操作系统是如何处理的。 图 2 用户应用程序调用系统调用 open() 的处理 系统调用因所用计算机的不同而不同。通常,除了所需的系统调用外,还要提供其他信息。这些信息的具体类型和数量根据特定操作系统和调用而有所不同。例如,为了获取输入,可能需要指定作为源的文件或设备以及用于存放输入的内存区域的地址和长度。当然,设备或文件和长度也可以隐含在调用内。 向操作系统传递参数有三种常用方法。最简单的是通过寄存器来传递参数。不过,有时参数数量会比寄存器多。这时,这些参数通常存在内存的块或表中,而块或表的地址通过寄存器来传递(图 3)。Linux 和 Solaris 就采用这种方法。 图 3 通过表来传递参数 参数也可通过程序放在或压入(pushed)到堆栈(stack),并通过操作系统弹出(popped)。有的系统偏爱块或堆栈方法,因为这些方法并不限制传递参数的数量或长度。 (编辑:ASP站长网) |