系统调用接口的主要任务是把进程从用户态切换到内核态。在具有保护机制的计算机系 统中,用户必须通过软件中断或陷阱,才能使进程从用户态切换为内核态。
在i386体系中,Linux的系统调用接口是通过调用软中断指令“int $ Oxso”使进程从用户态进入内核态的,这个过程也叫做“陷入”。当系统调用接口调用软中断指令“int $ Ox80”时,这个指令会发生一个中断向量码为128的中断请求,并在中断响应过程中将进程由用户态切换为内核态。
因为Linux只允许系统调用接口使用128这一个软中断向量,这也就意味着所有的系统调用接口必须共享这一个中断通道,并在同一个中断服务例程中调用不同的内核服务例程,所以,系统调用接口除了要引发“int $ Ox80”软中断之外,为了进人内核后能调用不同的内核服务例程,还要提供识别内核服务例程的参数,这个参数叫做“系统调用号”。也就是说,所有可为进程提供服务的内核服务例程都应具有一个唯一的系统调用号。当然,系统调用接口还应为内核服务例程准各必要的参数。
综上所述,系统调用接口需要完成以下几个任务:
●用软中断指令“int $ Ox80”发生一个中断向量码为128的中断请求,以使进程进入内核态。
●要保护用户态的现场,即把处理器的用户态运行环境保护到进程的内核堆栈。
●为内核服务例程准备参数,并定义返回值的存储位置。
●跳转到系统调用例程。
●系统调用例程结束后返回。
系统调用例程是系统提供的一个通用的汇编语言程序.其实它是一个中断向量为128的中断服务程序,其入口为system_call。它应完成的任务有:
●接受系统调用接口的参数。
●根据系统调用号,转向对应的内核服务例程,并将相关参数传遴给内核服务例程。
●在内核服务例程结束后,自中断返田到系统凋甩接口.
系统调用的过程如图所示。
从图中可以看到,系统调用接口是用高级语言来编写的,而通过调用中断指令陷入内核后的系统调用例程(即图中的系统调用处理程序)则是用汇编语言编写的。
为了通过系统调用号来调用不同的内核服务例程,系统必须维护一个系统调用表,这个表实质上就是系统调用号与内核服务函数的对照表。Linux是用数组sys_call_tabl来作为这个表的,在这个表的每个表项中存放着对应内核服务例程的指针,而该表项的下标就是该内核服务例程的系统调用号。Linux规定,在1386体系中,系统调用号由处理器的寄存器eax来传递。
图 系统调用的处理过程
系统调用表Sys_call_table的部分内容列举如下:
,Linux系统调用接口、系统调用例程和内核服务例程之间的关系