7.1 I/O系统的功能、模型与接口
I/O系统管理的主要对象是I/O设备和相应的设备控制器。I/O系统最主要的任务是,满足用户进程提出的I/O请求,提高I/O速度,提高设备的利用率,以及为更高层的进程方便地使用I/O设备提供手段。
7.1.1 I/O 系统的基本功能
为了满足系统和用户的请求,I/O系统应具有下述几方面的基本功能,其中,第一、第二方面的功能是为了方便用户使用I/O设备;第三、第四方面的功能是为了提高处理机和I/O设备的利用率;第五、第六方面的功能是为了给用户在共享设备时提供方便,以保证系统能有条不紊地运行,当系统发生错误时能及时发现错误,甚至自动修正错误。
1.能够隐藏 I/O 设备的细节
I/O设备的类型非常多,且彼此间在很多方面都存在差异,如它们接收和产生数据的速度、数据传输方向、数据粒度、数据的表示形式以及可靠性等方面。为了对这些千差万别的I/O设备进行控制,通常会为它们配置相应的设备控制器。这是一种硬件设备,其中包含若干个用于存放控制命令和参数的寄存器。用户通过这些命令和参数,可以控制I/O设备执行所要求的操作。显然,对于不同的I/O设备,需要有不同的命令和参数。例如,在对磁盘进行操作时,不仅要给出本次是读命令还是写命令,还要给出源数据或目标数据的位置,包括磁盘的盘面号、磁道号和扇区号。由此可见,要求程序员或用户编写直接面向这些I/O设备的程序是极其困难的。因此,I/O系统必须通过对I/O设备加以适当的抽象,以隐藏I/O设备的实现细节,仅向上层进程提供少量的、抽象的读/写命令,如read、write等。实际上,关于隐藏性问题,我们在第1章中已做了类似的介绍。
2.能够保证设备无关性
隐藏物理设备的细节,在早期的OS中就已实现,它可以方便用户对设备进行使用。保证设备无关性这一功能,是在较晚时才实现的,且是在隐藏I/O设备细节的基础上实现的。一方面,用户不仅可以使用抽象的I/O命令,还可以使用抽象的逻辑设备名来使用设备,例如,当用户要输出打印时,他只须提供(读或)写的命令(用于提出对I/O设备的要求)和抽象的逻辑设备名,如/dev/printer,而不必指明具体是哪一台打印机;另一方面,也可以有效地提高OS的可移植性和易适应性。对于OS本身而言,应允许在不需要将整个OS进行重新编译的情况下增添新的设备驱动程序,以方便新的I/O设备安装。如在Windows系统中,系统可以为新的I/O设备自动寻找和安装设备驱动程序,从而做到即插即用。
3.能够提高处理机和 I/O 设备的利用率
在一般的系统中,许多I/O设备间是相互独立的,能够并行操作,处理机与设备之间也能并行操作。因此,I/O系统的第三方面功能是尽可能地让处理机和I/O设备并行操作,以提高它们的利用率。为此,一方面要求处理机能快速响应用户的I/O请求,使I/O设备能够尽快运行起来;另一方面要求尽量减少在每个I/O设备运行时处理机的干预时间。在本章中将介绍许多有助于实现该目标的方法。
4.能够对 I/O 设备进行控制
对I/O设备进行控制是设备驱动程序的功能之一。目前对I/O设备有4种控制方式:①轮询的可编程I/O方式;②中断的可编程I/O方式;③直接存储器访问(direct memory access,DMA)方式;④I/O通道方式。应采用何种控制方式,与I/O设备的传输速率、传输的数据单位等因素有关。例如针对打印机、键盘等低速设备,由于它们传输数据的基本单位是字节(或字),故应采用中断的可编程I/O方式;而针对磁盘、光盘等高速设备,由于它们传输数据的基本单位是数据块,故应采用DMA方式,以提高系统的利用率。此外,I/O通道方式的引入,使得对I/O操作的组织和数据的传输,都能独立进行而无需CPU的干预。为了给上层软件和用户提供方便,显然I/O软件也应屏蔽掉这种差异,向上层软件和用户提供统一的操作接口。
5.能够确保对设备的正确共享
根据设备的共享属性,可将系统中的设备分为两类。①独占设备,进程应互斥地访问此类设备,即系统一旦把此类设备分配给某进程后,便由该进程独占,直至用完释放。典型的独占设备有打印机、磁带机等。系统在对独占设备进行分配时,还应考虑分配的安全性。②共享设备,是指在一段时间内允许多个进程同时访问的设备。典型的共享设备是磁盘,当有多个进程对磁盘执行读/写操作时,操作可以交叉进行而不会影响到读/写的正确性。
6.能够处理错误
大多数的设备都包括了较多的机械和电气部分,运行时容易出现错误和故障。从处理的角度看,可以将错误分为临时性错误和持久性错误。对于临时性错误,可通过重试操作来纠正它;只有在发生了持久性错误时,才需要向上层报告。例如,在磁盘传输数据过程中发生错误,系统并不认为磁盘已发生了故障,而是可以重新传输,一直重传多次后仍然有错,才会认为磁盘发生了故障。由于多数错误是与设备紧密相关的,因此对于错误的处理,应该尽可能地在接近硬件的层面上进行,即低层软件能够解决的错误就不向上层报告,因此高层也就不能感知。只有低层软件解决不了的错误才向上层报告,请求上层软件解决。
7.1.2 I/O 系统的层次结构与模型
I/O系统由I/O软件和I/O设备(硬件) 等组成。I/O软件涉及的面很宽,向下与硬件密切关联,向上又与文件系统、虚拟存储器系统和用户直接交互,它们都需要I/O系统来实现I/O操作。为使复杂的I/O软件能具有清晰的结构、更好的可移植性和易适应性,目前已普遍采用具有层次结构的I/O系统。该结构是将I/O系统中的设备管理模块分为若干个层次,每层都是利用其下层提供的服务来完成I/O功能中的某些子功能的,并且会屏蔽这些功能实现的细节,向上层提供服务。
1.I/O 系统的层次结构
通常把“I/O软件”组织成4个层次,它们包含于图7-2所示的I/O系统的层次结构中,图中的箭头表示I/O的控制流。各层次及其功能介绍如下。
- (1)用户层软件,用于提供与用户交互的接口,用户可直接调用该层所提供的与I/O操作有关的库函数对设备进行操作。
- (2)与设备无关的I/O软件,用于实现用户程序与设备驱动程序的统一接口、设备命名、设备保护以及设备的分配与释放等,同时为设备管理和数据传输提供必要的存储空间。
- (3)设备驱动程序,与硬件直接相关,用于执行系统对I/O设备发出的操作指令,换言之,是驱动I/O设备工作的驱动程序。
- (4)中断处理程序,用于保存被中断进程的CPU现场环境,保存完成后转入相应的中断处理程序处理中断,处理完成后再恢复被中断进程的CPU现场环境,最后返回被中断进程。
2.I/O 系统的模型
为了能更清晰地描述I/O系统中主要模块之间的关系,这里进一步介绍I/O系统的模型,即I/O系统中各种I/O模块之间的层次视图,如图7-3所示。
磁盘驱动器、控制器、中断处理程序、驱动程序
- (1)I/O系统的上/下接口。
- ① I/O系统接口。上接口是I/O系统接口,它是I/O系统与上层系统之间的接口,向上层系统提供对设备进行操作的抽象I/O命令,以方便上层系统对设备进行使用。有不少OS在用户层提供了与I/O操作有关的库函数供用户使用。在上层系统中有文件系统、虚拟存储器系统以及用户进程等。
- ② 软件/硬件接口。下接口是软件/硬件接口。它的上面是中断处理程序和用于不同设备的设备驱动程序。它的下面是各种设备的控制器,如CD-ROM控制器、硬盘控制器、键盘控制器、打印机控制器以及网络控制器等,它们都属于硬件。由于设备种类繁多,故该接口相当复杂。如图7-3所示,在上接口与下接口之间是I/O系统。
- (2)I/O系统的分层。
与前面所述的I/O软件的分层相对应,I/O系统本身也可分为以下3个层次。- ① 中断处理程序。它处于I/O系统的最低层,直接与硬件进行交互。当有I/O设备发来中断请求信号时,在中断硬件做了初步处理后,便转向中断处理程序。它首先保存被中断进程的CPU现场环境,然后转入相应设备的中断处理程序处理中断,在中断处理完成后又恢复被中断进程的CPU现场环境,并返回断点继续运行。
- ② 设备驱动程序。它处于I/O系统的次低层,是进程和设备控制器之间的通信程序,其主要功能是:将上层发来的抽象I/O请求转换为针对I/O设备的具体命令和参数,并把它们装入设备控制器中的命令寄存器和参数寄存器中,或者相反。由于设备之间的差异很大,每类设备的驱动程序都不同,故必须由设备制造厂商提供设备驱动程序,而不是由OS设计者来设计。因此,每当在系统中增加一个新设备时,都需要由设备制造厂商提供新的驱动程序。
- ③ 与设备无关的I/O软件。在现代OS的I/O系统中,I/O软件基本上都实现了与设备无关性,因此它们也称为与设备无关的软件、设备独立性软件、系统调用处理层,其基本含义是:I/O软件独立于具体使用的物理设备。由此带来的最大好处是:提高了I/O系统的可适应性和可扩展性,使它们能应用于许多类型的设备,而且在每次增加新设备或替换老设备时,都不需要对I/O软件进行修改,这样就方便了系统的更新和扩展。与设备无关的I/O软件的内容包括设备命名、设备分配、数据缓冲和数据高速缓冲等。
7.1.3 I/O 系统的接口
I/O系统与上层之间的接口,根据设备类型的不同,又可进一步分为若干类。在图7-3中给出了块设备接口、流设备接口和网络通信接口。
1.块设备接口
块设备接口是块设备管理程序与上层之间的接口。该接口反映了大部分磁盘存储器、光盘存储器、闪存等的本质特征,用于控制该类设备的I/O。
- (1)块设备。所谓块设备,是指数据的存取和传输都是以数据块为单位的设备。典型的块设备是磁盘。该设备的基本特征是传输速率较高,通常为每秒几十MB到几百MB。另一特征是可寻址,即能指定数据的输入源地址以及输出的目标地址,可随机读/写磁盘中的任一块;磁盘设备的I/O通常采用DMA方式。
- (2)隐藏了磁盘的二维结构。块设备接口将磁盘上的所有扇区从0到n-1依次编号,n是磁盘中的扇区总数。经过这样编号后,就可以把磁盘的二维结构变为线性序列。在二维结构中,每个扇区的地址需要用磁道号和扇区号来表示,换言之,块设备接口隐藏了磁盘地址是二维结构的这一情况。
- (3)将抽象命令映射为低层操作。块设备接口支持上层发来的、面向文件或设备的打开、读、写和关闭等抽象命令。该接口将上述命令映射为设备能识别的较低层的具体操作,例如,上层发来读磁盘命令时,它会先将抽象命令中的逻辑块号转换为磁盘的盘面号、磁道号和扇区号等。虚拟存储器系统也需要使用块设备接口,因为在进程运行期间,每当它所访问的页面不在内存中时,便会发生缺页中断,此时就需要利用I/O系统(通过块设备接口)从磁盘存储器中将所缺页面调入内存。
2.流设备接口
流设备接口是流设备管理程序与上层之间的接口。该接口又称为字符设备接口,它反映了大部分字符设备的本质特征,用于控制字符设备的I/O。
- (1)字符设备。所谓字符设备,是指数据的存取和传输是以字符(字节)为单位的设备,如键盘、打印机等。字符设备的基本特征是传输速率较低,通常为每秒几B至数千B。其另一特征是不可寻址,即不能指定数据的输入源地址以及输出的目标地址。字符设备在I/O时通常采用中断驱动I/O方式。
- (2)get操作和put操作。由于字符设备是不可寻址的,因而对它只能采取顺序存取方式。通常会为字符设备建立一个字符缓冲区(队列),设备的I/O字节流顺序地进入字符缓冲区(读入),或从字符缓冲区顺序地送出到设备(输出)。用户程序获取或输出字节的方法是采用get操作和put操作。get操作用于从字符缓冲区取得一个字节(到内存),并将它返回给调用者。而put操作则用于将一个新字节(从内存)输出到字符缓冲区,以待送出到设备。
- (3)in-control指令。因字符设备的类型非常多,且差异甚大,所以为了以统一的方式来处理它们,通常会在字符设备接口中提供一种通用的in-control指令。该指令中包含了许多参数,每个参数均表示一个与具体设备相关的特定功能。
- 因为大多数字符设备都属于独占设备,所以必须采取互斥方式实现共享。为此,字符设备接口提供了打开操作和关闭操作。在使用此类设备时,必须先用打开操作来打开设备。如果设备已被打开,则表示它正被其他进程使用。
3.网络通信接口
在现代OS中,都提供了面向网络的功能。但首先还需要通过某种方式,把计算机连接到网络上。同时OS也必须提供相应的网络软件和网络通信接口,以使计算机能通过网络同网络上的其他计算机进行通信,或上网浏览信息。由于网络通信接口涉及许多关于网络的知识,如网络中的各种硬件、网络通信协议和网络的层次结构等,这里将不再对其做专门的介绍,读者如有兴趣可查阅相关书籍以了解之。
7.2 I/O设备和设备控制器
I/O设备一般是由执行I/O操作的机械部分和执行I/O控制的电子部件组成的。通常会将这两部分分开,执行I/O操作的机械部分就是一般的I/O设备,而执行I/O控制的电子部件,则称为设备控制器或适配器(adapter)。微机和小型计算机中的控制器,常做成印刷电路卡的形式,因而它也常被称为控制卡、接口卡或网卡,可将它插入计算机的扩展槽中。在有的大、中型计算机系统中,还配置了I/O通道或I/O处理机。
7.2.1 I/O 设备
1.I/O 设备的类型
I/O设备的类型繁多,除了能将它们分为块设备和字符设备,独占设备和共享设备外,还可从设备的使用特性上将它们分为存储设备和I/O设备,以及从设备的传输速率上将它们分为低速设备、中速设备和高速设备。
- (1)按使用特性分类。第一类是存储设备,也称为外存、辅存,是用于存储信息的主要设备。该类设备存取速度较内存慢,但容量较内存却大得多,价格也便宜。第二类是I/O设备,它又可分为输入设备、输出设备和交互式设备。输入设备用于接收外部信息,如键盘、鼠标、扫描仪、视频摄像机等。输出设备用于将计算机处理后的信息送向处理机外部的设备,如打印机、绘图仪等。交互式设备则集成了上述两类设备,主要有显示器等,用于同步显示用户命令以及命令执行的结果。
- (2)按传输速率分类。按传输速率的高低,可将I/O设备分为三类。第一类是低速设备,其传输速率仅为每秒几字节至数百字节,典型的低速设备有键盘、鼠标等。第二类是中速设备,其传输速率为每秒数千字节至数十万字节,典型的中速设备有行式打印机、激光打印机等。第三类是高速设备,其传输速率为每秒数十万字节至千兆字节,典型的高速设备有磁带机、磁盘机、光盘机等。
- (3)按信息交换单位分类。 块设备、字符设备
- (4)按设备的共享属性分类 。 独占设备、共享设备
2.设备与设备控制器之间的接口
通常,设备并不直接与CPU进行通信,而是与设备控制器进行通信,因此,在I/O设备中应含有与设备控制器之间的接口,在该接口中有三类信号(见图7-4),各对应一条信号线。
(1)数据信号线。这类信号线用于在设备和设备控制器之间传送数据信号。对输入设备而言,由外界输入的信号经转换器转换所形成的数据,通常会先送入缓冲器中,当数据量达到一定的比特(字节)数后,再从缓冲器通过一组数据信号线传送给设备控制器,如图7-4所示。对输出设备而言,则是将从设备控制器经过数据信号线传送来的一批数据,先暂存于缓冲器中,经转换器做适当转换后再逐个字符地输出。
(2)控制信号线。这类信号线被作为由设备控制器向I/O设备发送控制信号的通路。该控制信号规定了设备将要执行的操作,如读操作(由设备向设备控制器传送数据),或写操作(从设备控制器接收数据),或执行磁头移动操作等。
(3)状态信号线。这类信号线用于传送指示设备当前状态的信号。设备的当前状态有正在读(或写)、设备已读(或写)完成、准备好了新的需要传送的数据等。
7.2.2 设备控制器
设备控制器的主要功能是,控制一个或多个I/O设备,以实现I/O设备和计算机之间的数据交换。它是CPU与I/O设备之间的接口,接收从CPU发来的命令,去控制I/O设备工作,使CPU能够从繁杂的设备控制事务中解脱出来。设备控制器是一个可编址的设备,当仅控制一个设备时,它只有一个唯一的设备地址;若设备控制器连接多个设备,则其应含有多个设备地址,每个设备地址对应一个设备。可把设备控制器分成两类:一类是用于控制字符设备的控制器,另一类是用于控制块设备的控制器。
1.设备控制器的基本功能
- (1)接收和识别命令。设备控制器能接收并识别处理机发来的多种命令。在控制器中具有相应的控制寄存器,用于存放接收的命令和参数,并对所接收的命令进行译码。例如,磁盘控制器可以接收CPU发来的read、write、format等15条不同的命令,而且有些命令还带有参数。相应地,在磁盘控制器中有多个寄存器和命令译码器。
- (2)数据交换。设备控制器能实现CPU与设备控制器之间、设备控制器与设备之间的数据交换。前者通过数据总线,由CPU并行地把数据写入设备控制器,或从设备控制器中并行地读出数据。后者通过寄存器,由设备将数据输入设备控制器,或由设备控制器传送数据给设备。为此,在设备控制器中须设置数据寄存器。
- (3)标志和报告设备的状态。设备控制器会记下设备的状态以供CPU了解。例如,仅当该设备处于发送就绪状态时,CPU才能启动设备控制器从设备中读出数据。为此,在设备控制器中应设置一状态寄存器,用其中的某一位来反映设备的某一种状态。当CPU将该寄存器的内容读入后,便可了解该设备的状态。
- (4)地址识别。设备控制器是一个可编址的设备,其必须能够识别自身所控制的每个设备的地址。当控制一个设备时,其只有一个唯一的设备地址;当控制多个设备时,其含有多个设备地址,并使每个设备地址对应一个设备。此外,为使CPU能向(或从)寄存器中写入(或读出)数据,这些寄存器都应具有唯一的地址。设备控制器应能正确识别这些地址,为此,在设备控制器中应配置地址译码器。
- (5)数据缓冲区。由于I/O设备的数据传输速率较低,而CPU和内存的速率却很高,故在设备控制器中必须设置一缓冲区。在输出时,用此缓冲区暂存由主机高速传来的数据,然后再以I/O设备所具有的传输速率将缓冲区中的数据传送给I/O设备。在输入时,缓冲区则用于暂存从I/O设备传来的数据,待接收到一批数据后,再将缓冲区中的数据高速地传送给主机。
- (6)差错控制。对于由I/O设备传送来的数据,设备控制器还兼管差错检测。若发现传送中出现了错误,则通常会将差错检测码置位,并向CPU报告,于是CPU将本次传送来的数据作废,并重新进行一次传送。这样便可保证数据输入的正确性。
- 值得注意的小细节:①一个/O控制器可能会对应多个设备:②数据寄存器、控制寄存器、状态寄存器可能有多个(如:每个控制/状态寄存器对应一个具体的设备),且这些寄存器都要有相应的地址,才能方便CPU操作。有的计算机会让这些寄存器占用内存地址的一部分,称为内存映像/O;另一些计算机则采用/o专用地址,即寄存器独立编址。
2.设备控制器的组成
由于设备控制器位于CPU与设备之间,它既要与CPU通信,又要与设备通信,还应具有按照CPU所发来的命令去控制设备工作的功能,因此,现有的大多数设备控制器都是由以下三部分组成的。
- (1)设备控制器与CPU的接口。该接口用于实现CPU与设备控制器之间的通信,在该接口中共有三类信号线:数据线、地址线和控制线。数据线通常与两类寄存器相连接:①第一类是数据寄存器,在设备控制器中可以有一个或多个数据寄存器,用于存放从设备传送来的数据(输入),或从CPU传送来的数据(输出);②第二类是控制/状态寄存器,在设备控制器中可以有一个或多个此类寄存器,用于存放从CPU送来的控制信息或设备的状态信息。
- (2)设备控制器与设备的接口。在一个设备控制器上,可以连接一个或多个设备。相应地,在设备控制器中便有一个或多个设备接口。在每个接口中都存在数据、控制和状态这三种类型的信号。设备控制器中的I/O逻辑会根据处理机发来的地址信号去选择一个设备接口。
- (3)I/O逻辑。I/O逻辑用于实现对设备的控制。它通过一组控制线与CPU交互,CPU利用该逻辑,向控制器发送I/O命令。CPU每当要启动一个设备时,一方面会将启动命令发送给设备控
制器,另一方面又会通过地址线把地址发送给设备控制器,由设备控制器根据I/O逻辑对地址进行
译码,再根据所译出的命令对所选设备进行控制。设备控制器的组成如图7-5所示。
7.2.3 内存映像 I/O
驱动程序将抽象I/O命令转换出的一系列具体的命令、参数等数据,装入设备控制器的相应寄存器中,由设备控制器来执行这些命令,具体实施对I/O设备的控制。这一工作可采用以下两种方法完成。
1.采用特定 I/O 指令形式
- 在早期的计算机(包括大型计算机)中,为实现CPU和设备控制器之间的通信,为每个控制寄存器分配一个I/O端口,端口号是一个8位或16位的整数,如图7-6 (a)所示。另外还设置了一些特定的I/O指令。例如,为了将CPU寄存器中的内容复制到设备控制器寄存器中,所须使用的特定I/O指令可表示如下:
io-store cpu-reg, dev-no, dev-reg
- 其中,cpu-reg是CPU的某个寄存器;dev-no是指定的设备控制器的地址;dev-reg是指定设备控制器中的寄存器。
- 如果是将CPU寄存器中的内容存入内存的某个单元(k)中,则将使用下面的指令:
Store cpu-reg, k
- 该方法的主要缺点是,访问内存和访问设备需要两种不同的指令。
2.采用内存映像 I/O 形式
- 在采用内存映像I/O形式这一方法中,在编址上不再区分内存单元地址和设备控制器中的寄存器地址,都采用k。当k值处于0~n-1这一范围时,被认为是内存地址,若k≥n,则被认为是某个设备控制器的寄存器地址。由图7-6 (b)可以看出,当k=n时,表示设备控制器0的第1个寄存器opcode的地址。因此,如果想将CPU寄存器中的内容传送到设备控制器0的第1个寄存器opcode,则只须使用如下所示的一般的存储指令即可。
Store cpu-reg, n
- 采用内存映像I/O形式统一了对内存和对设备控制器的访问方法,这无疑会简化I/O设备的编程。
7.2.4 I/O 通道
IO通道的概念、作用、为什么引入
1.I/O 通道设备的引入
虽然在CPU与I/O设备之间增加了设备控制器后,能大大减少CPU对I/O设备的干预,但当主机所配置的I/O设备有很多时,CPU的负担仍然会很重。为此,在CPU和设备控制器之间又增设了通道(channel),其主要目的是建立独立的I/O操作,即不仅使数据的传送能独立于CPU,而且使对I/O操作的组织、管理及其结束处理尽量独立,以保证CPU有更多的时间进行数据处理;或者说,其目的是使一些原来由CPU处理的I/O任务转由通道来承担,从而把CPU从繁杂的I/O任务中解脱出来。在设置了通道后,CPU只须向通道发送一条I/O指令。通道在接收到该指令后,便会从内存中取出本次要执行的通道程序,然后执行该程序;仅当通道完成了规定的I/O任务后,才向CPU发送中断信号。
实际上,I/O通道是一种特殊的处理机,它具有执行I/O指令的能力,并能通过执行(I/O)通道程序来控制I/O操作。但I/O通道又与一般的处理机不同,主要表现在以下两个方面:一是I/O通道指令类型单一(这是由通道硬件比较简单所致),其所能执行的命令主要局限于与I/O操作有关的指令;二是I/O通道没有自己的内存,所执行的通道程序是放在主机的内存中的,换言之,是I/O通道与CPU共享内存。
2.通道类型(了解)
前已述及,通道是用于控制外围设备(包括字符设备和块设备)的。由于外围设备的类型较多,且它们的传输速率相差甚大,因此通道也具有多种类型。这里,根据信息交换方式的不同,可把通道分成以下3类。
- (1)字节多路通道。
字节多路通道(byte multiplexor channel) 是一种按字节交叉方式工作的通道。它通常含有许多非分配型子通道,其数量可为几十到数百个,每个子通道均连接一台I/O设备,并控制该设备的I/O操作。这些子通道按时间片轮转方式共享主通道。当第一个子通道控制其I/O设备完成一个字节的交换后,其便会立即腾出主通道,让给第二个子通道使用;当第二个子通道也完成一个字节的交换后,同样也会把主通道让给第三个子通道;依此类推。当所有子通道轮转一周后,再由第一个子通道去使用字节多路主通道。这样,只要字节多路主通道扫描每个子通道的速率足够快,并且连接到子通道上的设备的速率又不是太高,便不会导致丢失信息。
图7-7所示为字节多路通道的工作原理。它所含有的多个子通道A,B,C,D,…,N,分别通过设备控制器各与一台设备相连。假定这些设备的速率相近,且都同时向主机传送数据。设备A所传送的数据流为A1,A2,A3,…;设备B所传送的数据流为B1,B2,B3,…;以此类推。把这些数据流合成后(通过主通道)送往主机,合成以后的数据流为A1,B1,C1,D1,…,A2,B2,C2,D2,…,A3,B3,C3,D3,…。
- (2)数组选择通道。
字节多路通道不适用于连接高速设备,这推动了按数组方式进行数据传送的数组选择通道(block selector channel) 的形成。这种通道虽然可以连接多台高速设备,但由于它只含有一个分配型子通道,在一段时间内只能执行一道通道程序,控制一台设备进行数据传送,这致使当某台设备占用了该通道后,便会一直由它独占,即使它无数据传送,闲置的通道也不允许其他设备使用,直至该设备传送完毕并释放该通道。可见,这种通道的利用率很低。 - (3)数组多路通道。
数组选择通道虽有很高的传输速率,但它每次只允许一个设备传输数据。数组多路通道(block multiplexor channel) 是通过结合两个优点(即数组选择通道传输速率高和字节多路通道能使各子通道分时并行操作)而形成的一种新通道。它含有多个非分配型子通道,因而这种通道既具有很高的数据传输速率,又能获得令人满意的通道利用率。也正因此,才使该通道能被广泛地用于连接多台高、中速的外围设备,其数据传送是按数组方式进行的。
3.“瓶颈”问题(了解)
- 由于通道价格昂贵,机器中所设置的通道数量势必较少,这往往又会使它成为I/O的瓶颈,进而造成整个系统吞吐量下降。例如,在图7-8中,假设设备1至设备4是四个磁盘,为了启动磁盘4,必须用通道1和设备控制器2;但若这两者已被其他设备占用,则必然无法启动磁盘4。类似地,若要启动磁盘1和磁盘2,则由于它们都要用到通道1,因而也不可能启动。这些就是由通道不足所造成的“瓶颈”现象。
- 解决“瓶颈”问题最有效的方法,便是增加设备到主机间的通路而不增加通道,如图7-9所示。换言之,就是把一个设备连接到多个设备控制器上,而把一个设备控制器又连接到多个通道上。图7-9中的设备1、2、3、4都有4条通往存储器的通路。例如,设备4可通过设备控制器1和通道1到存储器,也可通过设备控制器2和通道1到存储器。多通路方式不仅解决了“瓶颈”问题,而且提高了系统的可靠性,因为个别通道或设备控制器的故障不会使设备和存储器之间没有通路。
7.2.5 I/O 设备的控制方式
234的工作流程
对I/O设备的控制,早期是使用轮询的可编程I/O方式,后来发展为使用中断的可编程I/O方式。随着DMA控制器的出现,以字节为单位进行传输变为了以数据块为单位进行传输,这大大改善了块设备的I/O性能。I/O通道的出现,又使对I/O操作的组织和数据的传输都能独立进行,而无需CPU的干预。应当指出,在I/O设备的控制方式的整个发展过程中,始终贯穿着这样一条宗旨:尽量减少主机对I/O控制的干预,把主机从繁杂的I/O控制事务中解脱出来,以便其能更多地去完成数据处理任务。
1.使用轮询的可编程 I/O 方式
处理机对I/O设备的控制采取轮询的可编程I/O方式(程序轮询I/O方式),即在处理机向设备控制器发出一条I/O指令,启动输入设备输入数据时,要同时把状态寄存器中的忙/闲标志busy置为1,然后便不断地循环测试busy(称为轮询)。当busy=1时,表示输入机尚未输完一个字(节),处理机应继续对该标志进行测试,直至busy=0,表明输入机已将输入数据送入控制器的数据寄存器中。于是处理机将数据寄存器中的数据取出,送入内存的指定单元中,这样便完成了一个字(节)的I/O操作。接着再去读下一个数据,并置busy=1。图7-10 (a)所示为程序轮询I/O方式的流程。
在程序轮询I/O方式中,CPU的绝大部分时间都用于等待I/O设备完成数据I/O的循环测试中,这造成了对CPU的极大浪费。在该方式中,CPU之所以要不断测试I/O设备的状态,是因为在CPU中无中断机构,这使I/O设备无法向CPU报告它已完成了一个字节的输入操作。
2.使用中断的可编程 I/O 方式
- 当前,对I/O设备的控制,广泛采用中断的可编程I/O方式(中断驱动I/O方式),即当某进程要启动某个I/O设备工作时,便由CPU向相应的设备控制器发出一条I/O命令,然后立即返回继续执行原来的任务。设备控制器接收到命令后会按照该命令的要求去控制指定的I/O设备。此时,CPU与I/O设备并行操作。例如,在输入时,当设备控制器收到CPU发来的读命令后,便去控制相应的输入设备读数据。一旦数据进入数据寄存器,设备控制器便会通过控制线向CPU发送一中断信号,由CPU检查输入过程中是否出错;若无错,便向设备控制器发送取走数据的信号,然后再通过设备控制器以及数据线将数据写入内存指定单元中。图7-10(b)所示为中断驱动I/O方式的流程。
- 在I/O设备输入每个数据的过程中,可使CPU与I/O设备并行工作。仅当输入完一个数据时,才需要CPU花费极短的时间去做一些中断处理。这样可使CPU和I/O设备都处于忙碌状态,从而提高整个系统的资源利用率及吞吐量。例如,从终端输入一个字节的时间约为100ms,而将字节送入终端缓冲区的时间小于0.1ms。若采用程序轮询I/O方式,则CPU约有99.9ms的时间处于“忙等”中。但采用中断驱动I/O方式后,CPU可利用这99.9ms的时间去做其他事情,而仅用0.1ms的时间来处理由设备控制器发来的中断请求。可见,中断驱动I/O方式可以成百上千倍地提高CPU的利用率。
3.直接存储器访问(DMA)方式
- (1)DMA方式的引入。
- 虽然中断驱动I/O方式比程序轮询I/O方式更有效,但它仍是以字(节)为单位进行I/O操作的。每当完成一个字(节)的I/O操作,设备控制器便要向CPU请求一次中断。换言之,采用中断驱动I/O方式时的CPU是以字(节)为单位进行干预的。如果将这种方式用于块设备的I/O操作,显然是极其低效的。例如,为了从磁盘中读出1KB的数据块,需要中断CPU 1K次。为了进一步减少CPU对I/O设备的干预,引入了DMA方式,如图7-10(c)所示。
- 该方式的特点是:①数据传输的基本单位是数据块,即在CPU与I/O设备之间,每次至少传送一个数据块;②所传送的数据是从I/O设备直接送入内存的,或者相反;③仅在传送一个或多个数据块的开始和结束时,才须CPU干预,整块数据的传送是在DMA控制器的控制下完成的。可见,DMA方式较中断驱动I/O方式,又进一步提高了CPU与I/O设备的并行操作程度。
- (2)DMA控制器的组成。
- DMA控制器由3部分组成:主机与DMA控制器的接口;DMA控制器与块设备的接口;I/O控制逻辑。图7-11所示为DMA控制器的组成。这里主要介绍主机与DMA控制器的接口。
- 为了实现在主机与DMA控制器之间直接交换成块的数据,必须在DMA控制器中设置如下4类寄存器:①命令寄存器(command register,CR),用于接收从CPU发来的I/O命令,或有关控制信息,或设备的状态;②内存地址寄存器(memory address register,MAR),在输入时,它存放把数据从设备传送到内存的起始目标地址,在输出时,它存放由内存到设备的内存源地址;③数据寄存器(data register,DR),用于暂存从设备到内存或从内存到设备的数据;④数据计数器(data counter,DC),用于存放本次CPU要读或写的字(节)数。
- DMA控制器由3部分组成:主机与DMA控制器的接口;DMA控制器与块设备的接口;I/O控制逻辑。图7-11所示为DMA控制器的组成。这里主要介绍主机与DMA控制器的接口。
- (3)DMA控制器的工作过程。
- 当CPU要从磁盘读入一个数据块时,其便会向磁盘控制器发送一条读命令。该命令会被送入命令寄存器中。同时,还须将本次要读入的数据在内存中的起始目标地址送入内存地址寄存器中。将要读数据的字(节)数送入数据计数器中,还须将磁盘中的源地址直接送至DMA控制器的I/O控制逻辑上。然后,启动DMA控制器进行数据传送。以后,CPU便可去处理其他任务了,整个数据传送过程由DMA控制器进行控制。当DMA控制器已从磁盘中读入一个字(节)的数据并送入数据寄存器后,再挪用一个存储器周期,以将该字(节)传送到内存地址寄存器所指示的内存单元中。然后便对内存地址寄存器的内容加1,将数据计数器的内容减1,若减1后数据计数器的内容不为0,则表示传送未完,继续传送下一个字(节);否则,表示传送结束,并由DMA控制器发出中断请求。图7-12所示为DMA方式的工作流程。
- 当CPU要从磁盘读入一个数据块时,其便会向磁盘控制器发送一条读命令。该命令会被送入命令寄存器中。同时,还须将本次要读入的数据在内存中的起始目标地址送入内存地址寄存器中。将要读数据的字(节)数送入数据计数器中,还须将磁盘中的源地址直接送至DMA控制器的I/O控制逻辑上。然后,启动DMA控制器进行数据传送。以后,CPU便可去处理其他任务了,整个数据传送过程由DMA控制器进行控制。当DMA控制器已从磁盘中读入一个字(节)的数据并送入数据寄存器后,再挪用一个存储器周期,以将该字(节)传送到内存地址寄存器所指示的内存单元中。然后便对内存地址寄存器的内容加1,将数据计数器的内容减1,若减1后数据计数器的内容不为0,则表示传送未完,继续传送下一个字(节);否则,表示传送结束,并由DMA控制器发出中断请求。图7-12所示为DMA方式的工作流程。
4.I/O 通道方式
- (1)I/O通道方式的引入。
- 虽然DMA方式比中断驱动I/O方式已经显著减少了CPU的干预,即已由以字(节)为单位的干预减少到了以数据块为单位的干预,但CPU每发出一条I/O指令,也只能去读(或写)一个连续的数据块。而当我们需要一次去读多个数据块且将它们分别传送到不同的内存区域(或者相反)时,就须由CPU分别发出多条I/O指令并进行多次中断处理。
- I/O通道方式是DMA方式的发展,它可进一步减少CPU的干预,即把对一个数据块以读(或写)为单位的干预,减少为对一组数据块以读(或写)及有关的控制和管理为单位的干预。同时,又可实现CPU、通道和I/O设备三者的并行操作,从而更有效地提高整个系统的资源利用率。例如,当CPU要完成一组相关的读(或写)操作及有关控制时,只须向I/O通道发送一条I/O指令,以给出其所要执行的通道程序的起始地址和要访问的I/O设备,通道接到该指令后,通过执行通道程序便可完成CPU指定的I/O任务。
- (2)通道程序。
- 通道是通过执行通道程序并与设备控制器共同工作来实现对I/O设备的控制的。通道程序是由一系列通道指令(或称为通道命令)所构成的。通道指令与一般的机器指令不同,在它的每条指令中都包含了下列信息。
- ① 操作码,规定了指令所执行的操作,如读、写、控制等。
- ② 内存地址,表示字节送入内存(读操作)和从内存取出数据(写操作)时的内存起始地址。
- ③ 计数,表示本条指令所要读(或写)的数据的字节数。
- ④ 通道程序结束位P,用于表示通道程序是否结束;P=1表示本条指令是通道程序的最后一条指令。
- ⑤ 记录结束标志R,R=0表示本通道指令与下一条指令所处理的数据同属于一个记录,R=1表示这是处理某记录的最后一条指令。
- 下面给出了一个由六条通道指令所构成的简单的通道程序。该程序的功能是将内存中不同地址的数据写成多个记录。其中,前3条指令分别将813~892单元中的80个字符、1 034~1 173单元中的140个字符、5 830~5 889单元中的60个字符写成一个记录;第4条指令单独写一个具有300个字符的记录;第5、6条指令共写含300个字符的记录。
- 通道是通过执行通道程序并与设备控制器共同工作来实现对I/O设备的控制的。通道程序是由一系列通道指令(或称为通道命令)所构成的。通道指令与一般的机器指令不同,在它的每条指令中都包含了下列信息。
7.3 中断和中断处理程序
对于OS中的I/O系统,本章采取从低层向高层这一介绍方法,从本节开始首先介绍中断处理程序。中断在OS中有着特殊且重要的地位,它是多道程序得以实现的基础,没有中断就不可能实现多道程序,因为进程之间的切换是通过中断来完成的。另外,中断也是设备管理的基础,为了提高CPU的利用率并实现CPU与I/O设备并行执行,也必须有中断的支持。中断处理程序是I/O系统中最低的一层,它是整个I/O系统的基础。
7.3.1 中断简介
1.中断和陷入
- (1)中断(interrupt)。中断是指CPU对I/O设备发来的中断信号的一种响应。CPU暂停正在执行的程序,保存CPU现场环境后,自动转去执行该I/O设备的中断处理程序。执行完后再回到断点,继续执行原来的程序。I/O设备可以是字符设备,也可以是块设备以及通信设备等。由于中断是由外部设备引起的,故其又被称为外中断或硬中断。
- (2)陷入或陷阱(trap)。另外还有一种由CPU内部事件所引起的中断,例如进程在运算过程中发生了上溢或下溢,再如程序出错(如指令非法、地址越界、电源故障等)以及执行到程序中预设的软中断指令。通常把这类中断称为内中断,或软中断,或陷入。与中断一样,若系统发现了陷入事件,CPU也将暂停正在执行的程序,转去执行该陷入事件的处理程序。中断和陷入的主要区别是信号的来源不同,即来自CPU外部还是CPU内部。
2.中断向量表和中断优先级
- (1)中断向量表。为了实现处理上的方便,通常会为每种设备配以相应的中断处理程序,并把该程序的入口地址放在中断向量表的一个表项中,为每个设备的中断请求规定一个中断号,它直接对应中断向量表的一个表项。当I/O设备发来中断请求信号时,由中断控制器确定该请求的中断号,并根据该中断号查找中断向量表,从中取得该设备相应的中断处理程序的入口地址,这样便可转入中断处理程序并执行。
- (2)中断优先级。实际情况是经常会有多个中断信号源(引起中断的事件),每个中断信号源对服务要求的紧急程度并不相同,例如,键盘的中断请求的紧急程度不如打印机,而打印机的中断请求的紧急程度又不如磁盘等。为此,系统就需要为它们分别规定不同的优先级。
3.处理多中断信号源的方式
针对多中断信号源情况,当处理机正在处理一个中断时,又来了一个新的中断请求,这时应该如何处?例如,当系统正在处理打印机中断时,又收到了优先级更高的磁盘中断信号。
对于这种情况,可采用以下两种处理方式。
- (1)屏蔽(禁止)中断。当处理机正在处理一个中断时,将“屏蔽”掉所有的中断,即处理机对任何新到的中断请求都暂时不予理睬,而让它们等待。直到处理机已完成本次中断的处理后,才去检查是否有新的中断发生。若有,再去处理新的中断;若无,则返回被中断的程序。在该方法中,所有中断都将按顺序排队依次被处理。其优点是简单,但不能用于对实时性要求较高的中断请求。图7-13 (a)所示为多中断情况下的顺序中断处理。
- (2)嵌套中断。在设置了中断优先级的系统中,通常按以下规则来控制优先级:①当同时有多个优先级不同的中断请求时,CPU优先响应最高优先级的中断请求;②高优先级的中断请求可以抢占正在运行的低优先级中断的处理机,该方式类似于基于优先级的抢占式进程调度。例如,处理机正在处理打印机中断,当有磁盘中断到来时,可暂停对打印机中断的处理而转去处理磁盘中断。如果新到的是键盘中断,则由于它的优先级低于打印机的,故处理机会继续处理打印机中断。图7-13 (b)所示为多中断情况下的嵌套中断处理。
7.3.2 中断处理程序
流程。简答、选择
当一个进程请求I/O操作时,该进程将被挂起,直到I/O设备完成I/O操作后,设备控制器才会向CPU发送一中断请求,CPU响应后便转向中断处理程序,中断处理程序执行相应的处理,并在处理完后解除相应进程的阻塞状态。中断处理程序的处理过程可分成以下几个步骤。
1.测定是否有未响应的中断信号
每当设备完成一个字符(字或数据块)的读入(或输出),设备控制器便会向CPU发送一中断请求信号,请求CPU将设备已读入的数据传送到内存的缓冲区中(读入),或者请求CPU将要输出的数据传送给设备控制器(输出)。程序每当执行完当前指令后,CPU都要测试是否有未响应的中断信号。若没有,则继续执行下一条指令;若有,则停止原有进程的执行,准备转去执行中断处理程序,即为把CPU的控制权转交给中断处理程序做准备。
2.保护被中断进程的 CPU 现场环境
在把控制权转交给中断处理程序之前,需要先保护被中断进程的CPU现场环境,以便以后能恢复运行。首先需要保存的是从中断现场恢复到当前进程运行所需要的信息。通常由硬件自动将处理机状态字(processor status word,PSW) 和保存在程序计数器(program counter,PC) 中下一条指令的地址,保存在中断保留区(中断栈) 中。然后,把被中断进程的CPU现场信息,即所有CPU寄存器(如通用寄存器、段寄存器等) 的内容,都压入中断栈中,因为在处理中断时可能会用到这些寄存器。图7-14所示为一个简单的保护中断现场示意。该用户程序是指令在N位置时被中断的,程序计数器中的内容为N+1,所有寄存器的内容都被保留在中断栈中。
3.转入相应设备的中断处理程序
由CPU对各个中断信号源进行测试,以确定引起本次中断的I/O设备,并向提供中断信号的设备发送确认信号。在该设备收到确认信号后,就立即取消它所发出的中断请求信号。然后,将相应设备的中断处理程序的入口地址装入程序计数器中。这样,当CPU运行时,便可自动转入相应设备的中断处理程序。
4.处理中断
对不同的设备有不同的中断处理程序。该程序首先会从设备控制器中读出设备状态,以判别本次中断是正常完成中断还是异常结束中断。若是正常完成中断,中断处理程序便做结束处理。假如这次是字符设备的读操作,则来自输入设备的中断表明该设备已经读入了一个字节(字)的数据,并已放入数据寄存器中。此时中断处理程序应将该数据传送给CPU,再将它存入缓冲区中,并修改相应的缓冲区指针,使其指向下一个内存单元。若还有命令,则可再向设备控制器发送新的命令,进行新一轮的数据传送。若是异常结束中断,则根据发生异常的原因做相应的处理。
5.恢复 CPU 现场环境后退出中断
- 当中断处理完成以后,需要恢复CPU现场并退出中断。但是,此刻是否返回被中断的进程,取决于两个因素:①本中断是否采用了屏蔽(禁止)中断驱动I/O方式,若是,则返回被中断的进程;②针对中断处理方式为中断嵌套方式的情况,如果没有优先级更高的中断来请求I/O,则在中断处理完成后仍返回被中断的进程;反之,系统将处理优先级更高的中断请求。如果要返回到被中断的进程,则可将保存在中断栈中的被中断进程的CPU现场信息取出,并装入相应的寄存器中,其中包括该程序下一次要执行的指令的地址N+1、处理机状态字以及各通用寄存器和段寄存器的内容。这样,当CPU再执行本程序时,便会从N+1处开始,最终返回被中断的进程。
- I/O操作完成后,驱动程序必须检查本次I/O操作中是否发生了错误,并向上层软件报告,最终向调用者报告本次I/O的执行情况。除了上述的第4步(处理中断)外,其他步骤对所有I/O设备都是相同的,因而对于某种OS,如UNIX系统,其会把这些共同的部分集中起来,形成中断总控程序。每当要进行中断处理时,都要首先进入中断总控程序。而对于第4步,则对不同设备须采用不同的中断处理程序继续执行。图7-15所示为中断处理流程。
7.3.3 实例 :Linux 系统中断处理
- 在Linux系统中,中断会打断内核中进程的正常调度运行,因此要求中断处理程序尽可能简短。但是在实际的Linux系统中,当中断到来时,往往要完成大量的耗时工作。因此,期望中断处理程序运行得快,并且完成的工作多。这两个目标是相互制约的,为此,Linux系统中引入了上/下半部机制:上半部是中断处理程序,而下半部则是一些虽与中断有关但是可以延后执行的任务。上半部简单快速,执行时会禁止一些(或全部)中断;下半部延后执行,而且在执行期间可以响应所有的中断。这种机制可使系统处于中断屏蔽状态的时间尽可能短,以此来提高系统的响应能力。
- 在Linux系统中,不同的设备对应的中断不同,每个中断都会通过一个唯一的数字 (中断值) 进行标志,以使OS能够对中断进行区分。这些中断值通常被称为中断请求(interrupt request,IRQ),IRQ为数值型。在响应一个特定中断的时候,内核会执行一个函数,即中断处理程序。例如,由一个函数专门处理来自系统时钟的中断,而另一个函数专门处理由键盘产生的中断。一个设备的中断处理程序是其设备驱动程序的一部分,设备驱动程序是用于对设备进行管理的内核代码。
- 在Linux系统中,中断处理程序是普通的C函数,只不过这些函数必须按照特定的类型进行声明,以便内核能够以标准的方式传递中断处理程序的信息。在其他方面,它们与一般的函数没有差别。中断处理程序的设计可分为3个部分:①注册中断;②处理中断;③注销中断。
1.注册中断
- request_irq函数用于注册一个中断处理程序,声明位于文件linux/interrupt.h中。该函数若执行成功,则返回0;若返回非0值,则表示有错误发生,此时指定的中断处理程序不会被注册。
具体函数说明如下:1 int request_irq(unsigned int irq, 2 void(*handler)(int, void*, struct pt_regs *), 3 unsigned long flags, const char*devname, void*dev_id)
- 第1个参数irq:要分配的中断号。
第2个参数handler:一个指针,指向处理这个中断的实际中断处理函数。
第3个参数flags:与中断管理有关的各种选项,其定义位于文件linux/interrupt.h中,重要标
志包括IRQF_DISABLED、IRQF_TIMER、IRQF_SHARED等。
第4个参数devname:与中断相关的设备名,以ASCII表示,如键盘对应的“keyboard”等。
第5个参数*dev_id:主要用于共享中断线。
- 第1个参数irq:要分配的中断号。
- 该函数的使用示例如下:
1 if (request_irq(irqn,my_interrupt,SA_SHIRQ,"my_device",dev))
2 {
3 printk(KERN_ERR"my_device: cannot register IRQ %d, \n", irqn);
4 return –EIO;
5 }
2.处理中断
- 在Linux系统中,典型的中断处理程序声明为:
static irqreturn_t intr_handler(int irq, void *dev_id, struct pt_regs *regs)
该函数的返回值为irqreturn_t型,实际上为int型。该函数可能返回两个特殊值。- IRQ_NONE:当中断处理程序检测到一个中断,但该中断对应的设备并不是在注册中断处理程序期间指定的产生源时,返回该值。
- IRQ_HANDLED:当中断处理程序被正确调用且确实是它所对应的设备产生了中断时,返回该值。
- 具体的中断处理程序编写一般包括3个部分:①检查设备是否产生了中断;②清除中断产生标志;③执行相应的硬件操作。中断处理程序的特别之处在于,它是在中断处理时间内运行的,因此它的行为受到了某些限制:不能使用可能引起阻塞的函数;不能使用可能引起调度的函数。
- 下面所示的共享中断处理程序(short范例),使用中断来调用do_gettimeofday(功能是取得当前时间),并把当前时间打印到大小为一页的环形缓冲区,最后唤醒所有的读进程。
1 void short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs)
2 {
3 int value;
4 struct timeval tv;
5 /* 如果不是short,则立即返回 */
6 value = inb(short_base);
7 if (!(value & 0x80)) return;
8 /* 清除中断位 */
9 outb(value & 0x7F, short_base);
10 do_gettimeofday(&tv);
11 /* 写一个16B的记录; 假设PAGE_SIZE是16的倍数 */
12 short_head += sprintf((char *)short_head,"%08u.%06u/n",
13 (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));
14 if (short_head == short_buffer + PAGE_SIZE)
15 short_head = short_buffer; /* 绕回来 */
16 wake_up_interruptible(&short_queue); /* 唤醒所有的读进程 */
17 }
- 用来读取在中断时间里填满的缓冲区的节点是/dev/shortint,它内部的实现为中断的产生和报告做了特别的处理。每向设备写入一个字节都会产生一个中断;而在读设备时则会给出每次中断报告的时间。
3.注销中断
- 卸载驱动程序时,需要注销相应的中断处理程序,并释放中断请求线。可以调用函数free_irq来释放中断请求线。
void free_irq(unisigned int irq, void *dev_id)
- 如果指定的中断请求线不是共享的,那么该函数删除中断处理程序的同时,将会禁用该中断请求线。如果中断请求线是共享的,则仅删除dev_id所对应的中断处理程序,而这条中断线本身只有在删除了最后一个中断处理程序后才会被禁用。