1.5 用户与操作系统的接口
操作系统是用户与计算机系统之间的接口。用户在操作系统的帮助下,可以安全、可靠、方便、快速地使用计算机系统完成自己的各种任务。操作系统如何了解用户的意图,以便更好地服务用户呢?为此,操作系统向用户提供了使用计算机系统的接口,简称用户接口(User Interface,UI)。有两种接口方法:一种是提供给操作计算机的用户的操作接口,用户利用该接口来组织和控制作业的执行;另一种是提供给编程人员使用的低级接口—系统调用,编程人员在程序中利用该接口,向操作系统提出资源请求和一些功能服务。
1.5.1 用户与操作系统的操作接口
1.命令解释程序(Command Interpreter)
操作接口是以命令行的形式出现的,通过命令解释程序解释执行。有些操作系统将命令解释程序作为操作系统内核的一部分,如DOS操作系统。有些操作系统把命令解释程序当做一个特殊的程序,当用户登入系统或启动一个作业时,命令解释程序被激活运行。UNIX系统把它叫做Shell。这种接口提供的是一组操作命令或作业控制语言。用户使用这些命令,组织和控制作业的执行。命令解释程序的主要功能是获得用户的命令并解释执行。
命令解释程序有两种实现方法。
(1)命令解释程序本身包含了执行这些命令的代码。这种情况下,由于每个命令都对应自己的执行代码,因此,提供的命令个数决定了命令解释程序的大小。如DOS操作系统的命令解释程序就是这样实现的。
(2)由操作系统核心实现命令要求的功能。这种情况下,命令解释程序只是获得命令,并检查命令和参数的正确性,之后它调用实现命令的操作系统代码,完成命令的执行。这样命令解释程序较小,而且增加新的命令时,命令解释程序不受影响。UNIX操作系统的shell命令解释程序就是这样实现的。
2.图形用户接口(GUI)
另一个用户友好的接口就是图形用户接口(Graphic User Interface,GUI)。这是基于鼠标(mouse)的窗口和菜单系统。通过移动鼠标和单击按钮来定位屏幕上代表文件、程序和系统功能的映像或图标,用于运行一个程序、打开一个文件或目录或下拉一个命令菜单等。
究竟选择命令行还是GUI方式,这完全取决于个人的喜好。大多数UNIX系统的用户喜欢采用命令行接口方式,因为该系统提供了功能强大的Shell接口。而Windows用户则喜欢采用Windows的GUI环境,不喜欢使用DOS的命令行接口。
3.作业运行的控制命令
当用户使用批处理系统或分时系统时,如何控制其作业运行呢?也有以下两种控制方式。
(1)脱机作业控制命令。这是批处理系统提供给用户对作业控制时使用的命令。当进入系统的批处理作业被作业调度选中时,系统将按照用户提供的作业控制命令控制作业的执行。
作业控制语言通常包含两种类型的语句。一类是作业及其申请资源的说明语句,另一类是实现作业控制和具体操作功能的执行性语句。它大致应反映如下几方面要求:① 作业标识、作业说明,以及调度要求的参数;② 资源申请(主存、外设、CPU等);③ 程序和数据的控制功能;④ 调试功能;⑤ 控制转移功能;⑥ 作业撤销等。
通常,这类语言是解释执行,而不是编译执行的。负责解释作业控制语言语句的程序叫做作业解释程序或命令解释程序。
(2)交互式的作业控制命令。它提供给用户进行交互式作业或进程控制时使用的命令。实现这种方式的控制,系统提供了丰富的联机控制命令,又叫键盘命令,即Shell命令。
联机控制命令具体包括的功能如下:① 作业控制执行的命令(建立、修改、编译、连接、运行);② 资源申请(各种外设的使用和重定向);③ 文件的各种操作命令;④ 目录操作命令;⑤ 控制转移命令等。
每当一个新的用户登录系统,或开始一个新作业或进程时,命令行解释程序自动执行。等待用户输入命令并进行解释和执行。该方式下,系统的执行过程如图1.6所示。
图1.6 交互命令方式的程序执行过程
现代操作系统不再使用真正的批处理策略,但为了减少联机用户重复输入命令的负担,允许用户将一组复杂的操作系统命令组织成一个控制文件,然后批处理这个控制文件中的命令,使联机用户也可享受到自动批处理操作方式减轻用户负担的好处。
1.5.2 系统调用接口
系统调用提供了用户程序与操作系统内核的接口。所谓系统调用,就是操作系统内提供的一些子程序。编程人员通过使用系统调用命令,向操作系统提出资源请求或获得系统的一些功能服务,以取得操作系统的服务。系统调用接口通常是通过库函数调用映射进入操作系统的功能子程序的。
1.CPU的两种操作方式
由于计算机系统有许多用户,每个用户可能有若干个任务并发地在系统中执行。为了防止用户程序破坏操作系统或直接操作硬件,必须严格区分操作系统代码和用户代码。为此,许多处理机在处理机状态字(Processor Status Word,PSW)中增加一个执行方式位,区分两种操作方式:用户态(又称目态)和核心态。核心态(Kernel Mode)又叫管理态(Supervisor Mode)或特权态(Privileged Mode)。同时,处理机的执行状态决定了所能执行的操作:
(1)执行指令的特权性(指处理机能执行何种指令);
(2)存储器访问的特权性(指现行指令能访问存储器的哪些单元)。
为此,系统把CPU的指令集划分为特权指令(Privileged Instructions)和非特权指令。所谓特权指令是指关系系统全局的指令,如存取和操作CPU状态、启动各种外部设备、设置时钟时间、关中断、清主存、修改存储器管理寄存器、改变用户方式到核心方式和停机指令等。这类指令只允许操作系统使用,不允许用户使用。
操作系统程序运行在核心态。在核心态下,允许执行处理机的全部指令集(包括特权和非特权指令),访问所有的寄存器和存储区。
用户程序运行在用户态。在用户态下,只允许执行处理机的非特权指令,访问指定的寄存器和存储区。如果在用户态下企图执行一条特权指令,CPU就视其为非法指令,故障终止其运行。
2.系统调用功能
为了满足用户程序请求操作系统服务或请求系统资源,操作系统提供了功能丰富的系统调用命令。用户程序通过调用操作系统的这些服务程序,控制程序的启动、执行和使用系统中的各种资源和提供的服务。通常系统调用命令包括:
(1)进程控制。包括程序的正常和异常终止、程序的装入和执行、进程的创建和删除、得到和设置进程的属性、分配和释放主存,以及进程之间同步和通信等。
(2)文件管理。包括创建和删除文件、打开和关闭文件、读写和移动文件、得到和设置文件属性等。
(3)设备管理。包括请求和释放设备、读写设备、得到和设置设备的属性,以及连接和卸下设备等。
(4)其他服务。包括得到和设置系统的时间和日期、发送和接收消息等。
对于不同的操作系统,它们所提供的系统调用命令的条数、调用格式和所完成的功能不尽相同,这正如不同型号的计算机有不同的指令系统一样。一般来说,操作系统可提供的系统调用有数十条,乃至数百条。
系统调用很像预定义的函数或子程序,一般用在汇编语言指令中。有些系统调用直接用在高级语言程序中。
系统调用命令可以看成是机器指令的扩充。因为从形式上看,执行一条系统调用命令就好像执行一条功能很强的机器指令,所不同的是机器指令是由硬件执行的,而系统调用命令是由操作系统核心解释执行的。但从用户来看,操作系统提供了系统调用命令之后,就好像扩大了机器指令系统,增强了处理机的功能。因此,呈现在用户面前的是一台功能强、使用方便的虚拟处理机。
系统调用常常以API的形式出现。常用的有两种API,即Windows的Win32 API和基于POSIX系统的POSIX API(包括UNIX和Linux等)。系统维护一个系统调用接口表,每个系统调用都有一个名字,每个名字用一个数字表示,该数字就是查找这个表的索引。
3.系统调用的执行
从用户角度看,用户使用系统调用与一般的子程序调用非常相似,它们的执行会改变指令的执行流程,而且都可以共享和嵌套调用。一般的过程调用不涉及系统状态的转换,而系统调用的执行将使CPU的执行方式发生变化,将由用户态转换为核心态,执行相应的系统调用程序。完成系统调用功能后,CPU再由核心态转换为用户态,返回用户程序继续执行。
虽然系统调用命令的具体格式因系统而异,但从用户程序进入系统调用程序的步骤及其执行过程来看,却大致相同。通常,用户必须向系统调用命令处理程序提供必要的参数,以便根据这些参数进行相应的处理。用户程序执行到系统调用命令时,硬件把它作为一个软件中断对待,控制通过中断向量传递给操作系统的一个服务例程,改变用户方式到核心方式。这种方式又称为异常(Exception)或陷入(Trap)。
当执行一个系统调用时,它检查中断指令以决定出现了什么系统调用。所带参数决定了用户调用的服务类型并使用寄存器、堆栈(即一块主存区)进行参数传递。在验证参数的合法性后,去完成特定的系统调用功能。需要指出的是,这个被调用的系统子程序可能还要调用其他的子程序完成更基本的子功能,从而形成系统功能的嵌套调用。当系统调用执行完成时,系统要把执行是否成功,以及成功时的执行结果再回送给调用者。之后恢复处理机执行系统调用前的状态—用户态,返回到用户程序继续执行。系统调用的执行过程如图1.7所示。
图1.7 系统调用的执行过程
系统调用执行的一般过程可以概括为以下几步:
① 通过陷入(或异常)使系统切换到核心态,这需要硬件提供相应的支持。一旦CPU进入核心态,就可以按特权方式运行。
② 将程序计数器和处理机的当前状态存入任务的堆栈中。
③ 将系统调用号存入核心堆栈中。
④ 执行汇编代码来保存通用寄存器中的内容。
⑤ 调用相应的操作系统例程来完成系统调用。
⑥ 返回到用户方式。