系统调用如何实现
系统调用的实现与一般过程调用的实现相比,两者间有很大差异。对于系统调用,控制是由原来的用户态转换为系统态,这是借助于中断和陷入机制来完成的,在该机制中包括中断和陷入硬件机构及中断与陷入处理程序两部分。
中断和陷入硬件机构
图1所示为中断的处理过程。中断可进一步分为外中断和内中断。外中断是指由于外部设备事件所引起的中断,如通常的磁盘中断、打印机中断等;而内中断则是指由于CPU内部事件所引起的中断,如程序出错(非法指令、地址越界)等。内中断(trap)也被译为“陷入”或“陷阱”。
通常,陷入是由于执行了现行指令引起的,而中断则是由于系统中某事件引起的,该事件与现行指令无关。为了处理上的方便,通常针对不同的设备编制不同的中断处理程序,并把该程序的入口地址放在某特定的内存单元中。此外,不同的设备也对应着不?盏拇?砘?刺??SW,且把它放在与中断处理程序入口指针相邻接的特定单元中。在进行中断处理时,只要有了这样两个字,便可转入相应设备的中断处理程序,重新装配处理机的状态字和优先级,进行对该设备的处理,因此这两个字被称为中断向量。相应地,把存放这两个字的单元称为中断向景单元。类似地,对于陷入也有陷入向量表。由所有的中断向景和陷入向景构成了中断和陷入向量表。
系统调用号和参数的设置
通常,一个系统中设置了几十条甚至上百条系统调用,系统赋予每条系统调用一个唯一的系统凋用号。在有的系统中,直接把系统凋用号放在系统凋用命令中,如IBM370和早期的UNIX系统,是用系统调用命令的低8位存放系统调用号;在另一些系统中,则将系统调用号装入某指定寄存器或内存单元中,如MS-DOS是将系统调用号放在AH寄存器中。每一条系统调用都含有若干个参数,在执行系统调用时,设置系统调用所需的系数通常有两种方式。
(1)直接将参数送入相应的寄存器中。这是一种最简单的方式,MS-DOS采用的便是这种方式,即用MOV指令将各个参数送入相应的寄存器中。这种方式的主要问题是由于寄存器数量有限,因而限制了所设置参数的数目。
(2)参数表方式。将系统调用所需的参数放入一张参数表中,再将指向该参数表的指针放在某个指定的寄存器中。在当前大多数的OS中,如UNIX系统,便是采用了这种方式。该方式又可进一步分成直接和间接两种方式,如图2所示。在直接参数方式中,将所有的参数值和参数的个数N都放入一张参数表中;而在间接参数方式中,则在参数表中仅存放参数个数和指向真正参数数据表的指针。
系统调用的处理步骤
在设置了系统凋用号和参数后,便可执行一条系统凋用命令。不同的系统可采用不同的执行方式。在UNIX系统中,是执行CHMK命令;而在MS-DOS中则是执行INT21软中断。
系统调用的处理过程可分成以下3步。
(1)将处理机状态由用户态转为系统态;之后,由硬件和内核程序进行系统调用的一般性处理,即首先保护被中断进程的CPU环境,将处理机状态字PSW、程序计数器PC、系统调用号、用户找指针以及通用寄存器内容等压入堆栈;然后,将用户定义的参数传送到指定的地方保存起?怼?/p>
(2)分析系统调用类型,转入相应的系统调用处理子程序。为使不同的系统调用能方便地转向相应的系统调用处理子程序,在系统中配置了一张系统调用入口表。表中的每个表目都对应一条系统调用,其中包含该系统调用自带参数的数目、系统调用处理子程序的入口地址等。内核可利用系统调用号去查找该表,即可找到相应处理子程序的入口地址而转去执行它。
(3)在系统调用处理子程序执行完后,恢复被中断的或设置新进程的CPU现场,然后返?毡恢卸辖?袒蛐陆?蹋?绦??轮葱小?/p>
系统调用处理子程序的处理过程
系统调用的功能主要是由系统调用子程序来完成的。对于不同的系统调用,其处理程序将执行不同的功能。
下面以一条在文件操作中常用的creat命令为例来说明处理子程序的处理过程。进入creat的处理子程序后,内核将根据用户给定的文件路径名Path,利用目录检索过程,去查找指定义件的目录项。查找目录的方式可以用顺序查找法,也可用Hash查找法。如果在文件目录中找到了指定文件的目录项,表示用户要利用一个已有文件来建立一个新文件。但如果在该巳有(存)文件的属性中有不允许写属性,或者创建者不具有对该文件进行修改的权限,便认为是出错,随即做出错处理;若不存在访问权限问题,便将巳存文件的数据盘块释放掉,准备写入新的数据文件。如未找到指名文件,则表示要创建一个新文件,内核便从其目录文件中找出一个空目录项,并初始化该目录项,包括填写文件名、文件属性、文件建立日期等,然后将新建文件打开。