5.3 I/O软件层次

I/O软件通常组织成四个层次,如图5-11所示。每一层具有一个要执行的定义明确的功能和一个的定义明确的与邻近层次的接口。功能与接口随系统的不同而不同,所以下面的讨论并不针对一种特定的机器。我们将从底层开始讨论每一层。

阅读 ‧ 电子书库
图 5-11 I/O软件系统的层次

5.3.1 中断处理程序

虽然程序控制I/O偶尔是有益的,但是对于大多数I/O而言,中断是令人不愉快的事情并且无法避免。应当将其深深地隐藏在操作系统内部,以便系统的其他部分尽量不与它发生联系。隐藏它们的最好办法是将启动一个I/O操作的驱动程序阻塞起来,直到I/O操作完成且产生一个中断。驱动程序阻塞自己的手段有:在一个信号量上执行down操作、在一个条件变量上执行wait操作、在一个消息上执行receive操作或者某些类似的操作。

当中断发生时,中断处理程序将做它必须要做的全部工作以便对中断进行处理。然后,它可以将启动中断的驱动程序解除阻塞。在一些情形中,它只是在一个信号量上执行up操作;其他情形中,是对管程中的条件变量执行signal操作;还有一些情形中,是向被阻塞的驱动程序发一个消息。在所有这些情形中,中断最终的结果是使先前被阻塞的驱动程序现在能够继续运行。如果驱动程序构造为内核进程,具有它们自己的状态、堆栈和程序计数器,那么这一模型运转得最好。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

当然,现实没有如此简单。对一个中断进行处理并不只是简单地捕获中断,在某个信号量上执行up操作,然后执行一条IRET指令从中断返回到先前的进程。对操作系统而言,还涉及更多的工作。我们将按一系列步骤给出这一工作的轮廓,这些步骤是硬件中断完成之后必须在软件中执行的。应该注意的是,细节是非常依赖于系统的,所以下面列出的某些步骤在一个特定的机器上可能是不必要的,而没有列出的步骤可能是必需的。此外,确实发生的步骤在某些机器上也可能有不同的顺序。

1)保存没有被中断硬件保存的所有寄存器(包括PSW)。

2)为中断服务过程设置上下文,可能包括设置TLB、MMU和页表。

3)为中断服务过程设置堆栈。

4)应答中断控制器,如果不存在集中的中断控制器,则再次开放中断。

5)将寄存器从它们被保存的地方(可能是某个堆栈)复制到进程表中。

6)运行中断服务过程,从发出中断的设备控制器的寄存器中提取信息。

7)选择下一次运行哪个进程,如果中断导致某个被阻塞的高优先级进程变为就绪,则可能选择它现在就运行。

8)为下一次要运行的进程设置MMU上下文,也许还需要设置某个TLB。

9)装入新进程的寄存器,包括其PSW。

10)开始运行新进程。

由此可见,中断处理远不是无足轻重的小事。它要花费相当多的CPU指令,特别是在存在虚拟内存并且必须设置页表或者必须保存MMU状态(例如R和M位)的机器上。在某些机器上,当在用户态与核心态之间切换时,可能还需要管理TLB和CPU高速缓存,这就要花费额外的机器周期。