【操作系统】I/O设备

CPU和存储器不是操作系统惟一需要管理的资源。I/O设备也与操作系统有密切的相互影响。如图1-6所示,I/O设备一般包括两个部分:设备控制器和设备本身。控制器是插在电路板上的一块芯片或一组芯片,这块电路板物理地控制设备。它从操作系统接收命令,例如,从设备读数据,并且完成数据的处理。

在许多情形下,对这些设备的控制是非常复杂和具体的,所以,控制器的任务是为操作系统提供一个简单的接口(不过还是很复杂的)。例如,磁盘控制器可以接受一个命令从磁盘2读出11206号扇区,然后,控制器把这个线性扇区号转化为柱面、扇区和磁头。由于外柱面比内柱面有较多的扇区,而且一些坏扇区已经被映射到磁盘的其他地方,所以这种转换将是很复杂的。磁盘控制器必须确定磁头臂应该在哪个柱面上,并对磁头臂发出一串脉冲使其前后移动到所要求的柱面号上,接着必须等待对应的扇区转动到磁头下面并开始读出数据,随着数据从驱动器读出,要消去引导块并计算校验和。最后,还得把输入的二进制位组成字并存放到存储器中。为了要完成这些工作,在控制器中经常安装一个小的嵌入式计算机,该嵌入式计算机运行为执行这些工作而专门编好的程序。

I/O设备的另一个部分是实际设备的自身。设备本身有个相对简单的接口,这是因为接口既不能做很多工作,又已经被标准化了。标准化是有必要的,这样任何一个IDE磁盘控制器就可以适应任一种IDE磁盘,例如,IDE表示集成驱动器电子设备(Integrated Drive Electronics),是许多计算机的磁盘标准。由于实际的设备接口隐藏在控制器中,所以,操作系统看到的是对控制器的接口,这个接口可能和设备接口有很大的差别。

每类设备控制器都是不同的,所以,需要不同的软件进行控制。专门与控制器对话,发出命令并接收响应的软件,称为设备驱动程序(device driver)。每个控制器厂家必须为所支持的操作系统提供相应的设备驱动程序。例如,一台扫描仪会配有用于Windows 2000、Windows XP、Vista以及Linux的设备驱动程序。

为了能够使用设备驱动程序,必须把设备驱动程序装入到操作系统中,这样它可在核心态中运行。理论上,设备驱动程序可以在内核外运行,但是几乎没有系统支持这种可能的方式,因为它要求允许在用户空间的设备驱动程序能够以控制的方式访问设备,这是一种极少得到支持的功能。要将设备驱动程序装入操作系统,有三个途径。第一个途径是将内核与设备驱动程序重新链接,然后重启动系统。许多UNIX系统以这种方式工作。第二个途径是在一个操作系统文件中设置一个入口,并通知该文件需要一个设备驱动程序,然后一个操作系统文件中设置一个入口,并通知该文件需要一个设备驱动程序,然后重启动系统。在系统启动时,操作系统去找寻所需的设备驱动程序并装载之。Windows就是以这种方式工作。第三种途径是,操作系统能够在运行时接受新的设备驱动程序并且立即将其安装好,无须重启动系统。这种方式采用的较少,但是这种方式正在变得普及起来。热插拔设备,诸如USB和IEEE1394设备(后面会讨论)都需要动态可装载设备驱动程序。

“每个设备控制器都有少量的用于通信的寄存器。例如,一个最小的磁盘控制器也会有用于指定磁盘地址、内存地址、扇区计数和方向(读或写)的寄存器。要激活控制器,设备驱动程序从操作系统获得一条命令,然后翻译成对应的值,并写进设备寄存器中。所有设备寄存器的集合构成了I/O端口空间,我们将在第5章讨论有关内容。

在有些计算机中,设备寄存器被映射到操作系统的地址空间(操作系统可使用的地址),这样,它们就可以像普通存储字一样读出和写入。在这种计算机中,不需要专门的I/O指令,用户程序可以被硬件阻挡在外,防止其接触这些存储器地址(例如,采用基址和界限寄存器)。在另外一些计算机中,设备寄存器被放入一个专门的I/O端口空间中,每个寄存器都有一个端口地址。在这些机器中,提供在内核态中可使用的专门IN和OUT指令,供设备驱动程序读写这些寄存器用。前一种方式不需要专门的I/O指令,但是占用了一些地址空间。后者不占用地址空间,但是需要专门的指令。这两种方式的应用都很广泛。

实现输入和输出的方式有三种。在最简单的方式中,用户程序发出一个系统调用,内核将其翻译成一个对应设备驱动程序的过程调用。然后设备驱动程序启动I/O并在一个连续不断的循环中检查该设备,看该设备是否完成了工作(一般有一些二进制位用来指示设备仍在忙碌中)。当I/O结束后,设备驱动程序把数据送到指定的地方(若有此需要),并返回。然后操作系统将控制返回给调用者。这种方式称为忙等待(busy waiting),其缺点是要占据CPU,CPU一直轮询设备直到对应的I/O操作完成。

第二种方式是设备驱动程序启动设备并且让该设备在操作完成时发出一个中断。设备驱动程序在这个时刻返回。操作系统接着在需要时阻塞调用者并安排其他工作进行。当设备驱动程序检测到该设备的操作完毕时,它发出一个中断通知操作完成。

在操作系统中,中断是非常重要的,所以需要更具体地讨论。在图1-11a中,有一个I/O的三步过程。在第1步,设备驱动程序通过写设备寄存器通知设备控制器做什么。然后,设备控制器启动该设备。当设备控制器传送完毕被告知的要进行读写的字节数量后,它在第2步中使用特定的总线发信号给中断控制器芯片。如果中断控制器已经准备接收中断(如果正忙于一个更高级的中断,也可能不接收),它会在CPU芯片的一个管脚上声明,这就是第3步。在第4步中,中断控制器把该设备的编号放到总线上,这样CPU可以读总线,并且知道哪个设备刚刚完成了操作(可能同时有许多设备在运行)。

一旦CPU决定取中断,通常程序计数器和PSW就被压入当前堆栈中,并且CPU被切换到用户态。设备编号可以成为部分内存的一个引用,用于寻找该设备中断处理程序的地址。这部分内存称为中断向量(interrupt vector)。当中断处理程序(中断设备的设备驱动程序的一部分)开始后,它取走已入栈的程序计数器和PSW,并保存之,然后查询设备的状态。在中断处理程序全部完成之后,它返回到先前运行的用户程序中尚未执行的头一条指令。

第三种方式是,为I/O使用一种特殊的直接存储器访问(Direct Memory Access,DMA)芯片,它可以控制在内存和某些控制器之间的位流,而无须持续的CPU干预。CPU对DMA芯片进行设置,说明需要传送的字节数、有关的设备和内存地址以及操作方向,接着启动DMA。当DMA芯片完成时,它引发一个中断,其处理方式如前所述。有关DMA和I/O硬件会在第5章中具体讨论。

中断经常会在非常不合适的时刻发生,比如,在另一个中断程序正在运行时发生。正由于此,CPU有办法关闭中断并在稍后再开启中断。在中断关闭时,任何已经发出中断的设备,可以继续保持其中断信号,但是CPU不会被中断,直至中断再次启用为止。如果在中断关闭时,已有多个设备发出了中断,中断控制器将决定先处理哪个中断,通常这取决于事先赋予每个设备的静态优先级。最高优先级的设备赢得竞争。

发布了374 篇原创文章 · 获赞 14 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105378210