Linux基础教程(1)操作系统基础清华大学计算机基础教育课程系列教材汤荷美董渊李莉程志锐编著第5章设备5.1设备介绍5.2数据传输5.3I/O软件原理5.4小结习题计算机系统中所有的软硬件都是由操作系统控制和管理的,其中除了CPU和内存之外的几乎所有硬件通常统称为外部设备。操作系统中设备管理的任务是负责控制并操纵所有的设备,实现不同外部设备之间、外部设备和内存以及CPU之间的数据传输,使它们协同工作,在获得最佳效率、提供良好服务的同时,尽可能地提供统一的用户命令和函数调用接口,对用户屏蔽不同设备之间的差异。在Linux等操作系统中,所有的设备统一当作文件来处理,称为设备文件,和其他文件一样,这种文件可以使用处理文件的标准系统调用打开、关闭和读写。操作系统设备管理部分通常也采用分层结构,底层是设备相关部分,直接和相应的设备打交道,负责设备的具体控制,并向上层提供一致的访问接口,通常称为设备驱动程序。上层通常是和设备无关的,这个部分接受来自上层的具体访问请求,并根据实际情况把这些访问请求转向具体的设备驱动程序接口,和设备进行通信,接受驱动程序的执行结果。本章简要介绍设备管理中数据传输控制的基本原理,并以此为基础,学习设备分配概念及设备驱动程序。5.1设备介绍操作系统中用于设备管理的内核代码在整个内核中是数量最多的部分。外部设备给用户提供进行计算机基本操作以及完成各种特定功能的接口,用户需要交给计算机处理的所有数据都必须通过特定的外部设备来传输到内存和CPU。设备可以被简单地看作是由机械部分和电子部分组成。在微机系统中,控制器一般都有自己的控制和状态寄存器,独立于系统的内存空间,所有设备的寄存器组成计算机的输入/输出空间(称为I/O空间),操作系统通过设备驱动程序访问I/O空间,管理设备控制器,由控制器具体操纵设备完成预定的任务。5.1.1设备分类外部设备可以按照不同的标准进行分类。从普通用户的角度,按照设备的使用特性来划分,普通微机的外部设备主要包括存储设备和输入输出设备。从操作系统管理的角度来看,按照设备传输信息的组织形式,外部设备可以划分为字符设备、块设备和网络设备。这也是Linux操作系统进行设备管理过程中的划分方式。Linux系统中,每一个设备对应于一个设备文件,具有独立的设备号。主设备号描述相应的设备驱动程序,从设备号用来区分同一驱动程序控制下的不同设备实例。5.1.2设备实例——磁盘磁盘是计算机系统中最常见的存储设备,IDE磁盘是现在PC上使用最广泛的硬盘类型,每个IDE控制卡支持两个独立的盘(可以是硬盘、光驱等),每个盘在Linux里表现为独立的块设备。操作系统本身以及大量的用户数据都存放在磁盘中,同时,Linux系统还使用一部分磁盘空间作为内存交换空间,实现虚拟内存管理。所有实际的磁盘都由多层盘片组成,磁盘的物理结构示意图参看图5.1。磁盘的扇区个数、磁头个数和柱面个数三个数据称为磁盘的基本几何参数。如果知道每个扇区的具体容量(单位扇区容量),整个磁盘的容量就是这三个几何参数和单位扇区容量的乘积。图5.1磁盘设备结构示意图磁盘数据的读写需要一定的时间,这个时间具体由三个部分组成,一是磁头跨越磁道径向移动到要读写道的时间,一般称为寻道时间;二是要读写磁道等待数据移动到磁头位置的时间,称为旋转延迟时间;三是具体读写数据的时间,称为数据传输时间。在实际的使用过程中,通常把整个磁盘划分为小的管理单元,称为磁盘分区(partition)。在Linux系统中,每一个磁盘分区都可以安装一个独立的文件系统,具有独立的设备号,主设备号对应着磁盘本身,从设备号对应于该磁盘上具体的分区,同时,系统还使用惟一的设备文件来表示磁盘分区,比如设备文件/dev/hda5,hda表示该磁盘的IDE接口上的第1个磁盘(依此类推,hdb、hdc表示该接口上第2、第3个磁盘等等),对应于主设备号,5是它的从设备号。5.2数据传输数据在外部设备与处理机、内存之间的传输控制,是操作系统设备管理的主要功能,从设备到内存和处理机的数据传输称为输入(input),从内存和处理机到设备的传输称为输出(output),因此数据传输也通常称为数据I/O。一般的PC中,CPU、内存通过系统总线连接在一起,总线定义了所有设备之间通信的协议,各种设备都直接或者间接地连接在总线上,设备和处理机以及内存之间的数据传输必须通过总线来实现。数据传输控制要求能够实现数据在外部设备和内存、CPU之间快速、可靠的传送,充分发挥设备资源的能力,同时使用尽可能少的系统开销。5.2.1数据传输控制方式PC机中常用的数据传输控制方式包括程序直接控制、中断和内存直接访问三种。1.程序直接控制程序直接控制方式就是由用户进程来直接控制内存,或者CPU和外部设备之间的数据传输。用户进程是数据传输的控制者,在进程执行过程中需要传输数据时,通过CPU启动外部设备,继续占用处理机,进入查询测试等待。该进程不停地查询设备是否准备好,一旦数据准备好,完成数据传输,继续下面的执行。在整个传输过程中,用户进程一直占用CPU,而CPU所做的大量工作是查询设备的状态,因此这种传输方式也称为查询测试方式。如果采用这种方式来传输大量的数据,由于外部设备的速度比CPU要慢很多,因此大量的时间浪费在查询上,设备的利用率可以得到一定程度的保证,但是CPU资源却得不到有效的利用。2.中断方式针对程序直接传输浪费CPU资源的缺陷,引入了中断(interrupt)技术。中断方式要求CPU和外部设备之间有相应的中断请求线,外部设备可以通过中断请求线打断CPU正在进行的工作,转入相应的操作。中断方式下,当用户进程执行过程中需要数据传输时,通过CPU启动外部设备,自己放弃处理机资源,进入等待状态,外部设备进行相应的数据准备工作,而CPU可以经过调度被其他进程所使用。直到外部数据准备完成之后,设备通过中断请求线发出中断,发生调度,CPU转入中断处理程序,进行相应的数据操作,而等待数据传输的进程被唤醒转入就绪状态,在适当的时候占有处理机,并得到数据继续执行。利用中断方式,在用户进程等待设备准备数据到发出中断这一段时间内,CPU可以执行其他进程,提高了处理机和外部设备的并行程度,一定程度上解决了处理机资源浪费的问题。但是,如果设备每一次进行数据传输都只能准备少量的数据的话,系统的效率也得不到有效的提高。每次只传输少量数据,每次都要发生中断,需要进行多次进程调度和进程现场切换,就要耗费大量的CPU资源。同时,如果有多个设备同时进行大规模的数据传输,整个系统中的中断次数会急剧增加,造成CPU无法及时响应中断,出现数据丢失的情况。因此,必须采取一定的措施保证设备在一次中断发生之前进行相当规模的数据传输。3.直接内存访问直接内存访问(DirectMemoryAccess,DMA)可以用来解决中断方式的上述问题,它在外部设备和内存之间开辟直接的数据通道,设备控制器具有。更强的功能,可以窃取CPU的一个工作周期,不需要CPU的参与直接把数据放入到内存中指定的位置。DMA方式传输数据时,正在执行的用户进程通过CPU发出数据传输请求,同时把数据存放地址和数据量这些主要参数通知DMA控制器,用户进程转入等待状态,CPU可以执行其他进程,外部设备不断地窃取CPU的工作周期,把准备好的数据不断地写入内存相应的位置,直到所要求的数量全部完成或者发生错误,才通过中断线通知CPU进行相应的中断处理,这时需要数据的用户进程转入就绪状态,在适当的时间占用CPU继续执行。在整个数据传输过程中,DMA控制器只是获取CPU的工作周期,并不要求它做额外的处理,只是到全部数据传输完成或者出现错误才发生中断,这样就可以保证使用尽可能少的中断来完成尽可能多的数据传输。在前两种数据传输控制方式中,数据传输都是围绕CPU开展的,CPU得知设备准备好数据之后,直接控制数据的传输,把它们放到内存中适当的位置,由用户进程使用,二者的差别是CPU获得设备状态的方式不同,前者靠不断地查询,后者是靠设备发送中断请求。而在DMA方式中,数据交换是围绕内存进行的,外部设备和内存之间直接进行数据传输,数据传输过程中不需要CPU的干预,只有数据传输完成之后才通知CPU。5.2.2数据传输关键技术从上面的介绍可以看到,中断技术在整个数据传输过程中占有相当重要的地位,它是提高外部设备和CPU的并行程度、改善系统整体性能的关键。另外一个关键技术是缓冲,利用这样的技术,可以大大地减少外部设备的访问次数,实现系统整体性能的提高。1.中断中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序,而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处,继续执行或者调度新的进程执行的过程。引起中断发生的事件称为中断源,在计算机系统中,外部设备数据传输过程中发生的中断属于I/O中断,是中断源中的一大类,其他中断源有周期性的时钟中断、电源掉电产生的中断等等。中断源向CPU发出的请求中断处理信号称为中断请求,而CPU收到中断请求后转入相应的事件处理程序称为中断响应。按照中断源产生的位置,中断分为内中断和外中断。内中断由处理机和内存内部产生,通常也称为陷阱,它包括程序运算引起的各种错误和分时系统中的时间片中断等等。外中断由处理机和内存之外的设备发出,包括上面讲到的I/O中断和时钟、电源中断等等。并不是所有中断请求都会得到及时的响应。很多情况下,比如系统正在进行进程调度或者内存调度操作,为了保证操作的封闭性,这时不允许CPU响应中断,这种情况称为禁止中断或者关中断。CPU禁止中断,完成必要的操作之后必须通过硬件重新设置才能够接收中断,这个过程称为开中断。关中断之后,CPU不接受任何中断请求。另外一种情况是CPU可以有选择地响应某些中断,称为中断屏蔽。中断屏蔽是指中断请求产生之后,系统用软件方式有选择地封锁部分中断,而允许其余部分中断仍然能够得到响应。并不是所有中断请求都具有平等地得到响应的权利,根据中断源的紧急程度,操作系统对不同的中断请求赋予不同的优先级。如果两个中断请求同时发生,优先级高的中断有权在优先级低的中断之前得到响应。各种中断源的优先级在系统设计时设置完成。而CPU收到中断请求后,首先要进行进程切换,原来正在执行的进程放弃处理机,保护现场完成之后,转入相应的事件处理程序,进行中断处理。一台PC机中断号的个数是有限的,在Linux系统中,中断号当前使用情况记录在文件/proc/interrupts中。如果安装了很多设备,大家就必须采取一定的措施来共享有限的中断号资源,称为中断共享,实现中断共享需要设备和中断处理程序两个方面的支持,一方面CPU能够通过询问设备而知道该设备是否产生过中断,另一方面中断处理程序能够向前传递别的设备产生的中断信号。2.缓冲缓冲是计算机系统中为了解决外部设备和CPU之间处理速度的匹配问题,减少外部设备中断请求次数而设置的暂时存放数据的区域。根据数据传输控制方式,可以有两种实现方式。一是采用硬件缓冲器,在外部设备中设置缓冲,外部设备每次传输数据之前,可以利用缓冲器准备更多的数据,提高每一次传输的数据量,减少传输的次数。可以想象,如果某个设备每次只准备一个字节,传输1KB数据需要发生一千多次中断请求,即便是DMA方式,也需要一千次获取CPU工作周期,每次传输都要获取总线使用权,对其他进程的影响会是很大的。如果该设备设置1KB大小的缓冲器,可以先把数据都准备在缓冲中,然后只需要一次中断,一次性掌握CPU和总线就可以完成数据传输,系统的效率可以得到明显的改善。另一种方法是在内存中划分专用的数据缓冲区,所有的数据I/O都要经过这些缓冲区,每次发生数据传输后并不清除缓冲区中数据,下一次访问数据时首先在缓冲区中查找,如果缓冲区中有,则不需要启动外部设备就可以得到需要的数据,如果缓冲区中没有需要的数据,再启动设备。这样,经过一段时间的积累,经常访问的数据基本都在缓冲区中,系统启动设备的次数就大大降低,可以提高数据I/O的整体效率。前一种实现方法主要