8.4.3 DMA 方式

第 3 版 · OCR 辅助 · 原书检索 · 文字用于定位,公式与图表请回原页核验 · 本次导入快照

##### 8.4.3 DMA 方式
DMA(direct memory access)称为直接存储器存取,该I/O方式用专门的DMA接口硬
件来控制外设与主存间的直接数据交换,数据不通过CPU。通常把专门用来控制总线进行
DMA传送的接口硬件称为DMA控制器。在进行DMA传送时,CPU 让出总线控制权,由
DMA控制器控制总线,通过“窃取”一个主存存储周期完成和主存之间的一次数据交换,或
独占若干存储周期完成一批数据的交换。
DMA方式主要用于磁盘等高速设备的数据传送。这类高速设备的记录方式多采用数
据块组织方式,数据块之间有间隙,因而数据传输时数据块之间的时间间隔较长,而数据块
内部数据间的传输时间间隔较短,因此,这类设备大多采用成批数据交换方式。
DMA方式与中断I/O方式一样,也是采用“请求-响应”的方式,只是中断I/O方式请
求的是处理器的时间,而DMA方式下请求的是总线控制权。图8.24给出了进程P1在磁
盘和主存之间进行数据交换的过程示意图。首先,
传送参数的设置
查询方式
P1采用程序查询方式设置传送参数,通过执行相应
(初始化)
的指令对有关参数寄存器进行初始化;然后CPU执
寻道
中断方式
行1/O指令发出“寻道”命令到磁盘控制器,由磁盘
控制器控制磁盘驱动器开始移动磁头,同时,CPU 切
查找扇区
中断方式
换到其他进程(如 P2)执行;当磁盘完成寻道操作
后,向CPU发出“寻道结束”中断请求;CPU响应并
连续读写
DMA 方式
处理该中断请求,中止正在执行的进程 P2,在中断服
务程序中通过执行I/O指令发出“查找扇区”命令到
结束、校验 ------- 中断方式
磁盘控制器,CPU启动“查找扇区”命令后,返回被中
图8.24 DMA方式进行磁盘
止的进程 P2 执行;当磁盘完成扇区查找操作,就向
数据传送过程
CPU发出“查找结束”中断请求;CPU响应并处理该
中断,又一次中止正在执行的进程 P2,然后在中断服务程序中启动进行 DMA传送,由
DMA控制器控制数据在主存和磁盘之间进行数据传送;CPU启动 DMA传送后,又回到被
中止的进程 P2继续执行,直到 DMA传送结束;此时,由DMA控制器发出“DMA 结束”中
断请求,CPU响应并处理该中断请求,对传送的数据进行校验等后处理。
1.3种 DMA 方式
由于 DMA控制器和CPU共享主存,所以可能出现两者争用主存的现象,为使两者协
调使用主存,DMA通常采用以下3种方式之一进行数据传送。
(1)CPU停止法。DMA传输时,由DMA控制器发一个停止信号给 CPU,使 CPU 脱
第8章
301


<!-- page: 319 -->

计算机组成与系统结构(第3版)
302
离总线,停止访问主存,直到 DMA传送一块数据结束。
(2)周期挪用法。DMA传输时,CPU让出一个总线事务周期,由 DMA控制器挪用一
个存储周期来访问主存,传送完一个数据后立即释放总线。这是一种单数据传送方式。
(3)交替分时访问法。每个存储周期分成两个时间片,一个给CPU,另一个给 DMA 控
制器,这样在每个存储周期内,CPU和DMA控制器都可访问存储器。
2. DMA操作步骤
DMA控制器与设备控制器一样,其中也有若干寄存器,用于存放I/O传送所需的各种
参数。这些寄存器包括主存地址寄存器、字计数器、控制寄存器、设备地址寄存器等,此外,
还有其他的控制逻辑,能控制设备通过总线与主存直接交换数据。DMA方式的1/O 操作
过程由以下步骤来完成。
第1步:DMA控制器的初始化。
在进行数据传送之前,CPU先执行一段初始化程序,完成对 DMA控制器中各参数寄
存器的初始值设定。主要操作包括以下3方面。
(1)准备内存区。若是从外设输入数据,则进行内存缓冲区的申请,并对缓冲区进行初
始化;若是输出数据到外设,则先在内存准备好数据。
(2)设置传送参数。执行I/O访问指令来测试外设状态,并对 DMA控制器设置各种
参数,如将内存首址送地址寄存器;字计数值送字计数器;传送方向送控制寄存器;设备地址
送设备地址寄存器。
(3)发送“启动 DMA传送”命令,然后调度CPU执行其他进程。
第2步:DMA数据传送。
CPU对DMA控制器进行初始化并发送“启动 DMA传送”命令后,就把数据传送的工
作交给了DMA控制器。在整个 DMA传送过程中,不再需要CPU的参与,完全由DMA控
制器实现数据的传送。
DMA控制器给出内存地址,并在其读/写线上发出“读”命令或“写”命令,随后在数据
总线上给出数据。DMA控制器每完成一个数据的传送,就将字计数值减1,并修改主存地
址。当字计数器为0时,完成所有I/O操作。
第3步:DMA结束处理。
当字计数器为0,则发出“DMA结束”中断请求信号给 CPU,转入中断服务程序,进行
DMA 结束处理工作。
从上述过程来看,DMA方式与程序查询和中断I/O方式不同,CPU不直接执行I/O
访问指令来实现数据传送,而只是进行一些初始化等辅助工作。DMA方式的I/O 过程如
图8.25所示。
DMA方式下,CPU仅在最初的 DMA控制器初始化和最后“DMA结束”中断处理时参
与I/O,而数据传送过程完全由 DMA控制器进行控制,不需 CPU参与,因而 CPU 用于
I/O的开销非常小。
下面举例说明使用 DMA方式进行硬盘和主存之间的数据传送时 CPU的开销。
例8.5 假定CPU的主频为500MHz,即 CPU每秒钟产生500×10°个时钟周期。硬
盘采用DMA方式进行数据传送,其数据传输率为4MB/s,每次 DMA传输的数据量为
4KB,要求没有任何数据被错过。如果CPU在 DMA控制器初始化和外设启动等方面需要


<!-- page: 320 -->

系统互连及输入输出组织
copy_string_to_kernel(strbuf,kernelbuf,n);
initialize_DMA();
*DMA_control_port=START;
scheduler();
//将字符串复制到内核缓冲区
//初始化DMA控制器(准备传送参数)
//发送“启动DMA传送”命令
//阻塞用户进程P,调度其他进程执行
(a)“字符打印”系统调用处理例程
acknowledge_interrupt();
unblock_user();
return_from_interrupt();
//中断回答(清除中断请求)
//用户进程P解除阻塞,进入就绪队列
// 中断返回
(b)“DMA结束”中断服务程序
图8.25 DMA控制1/O过程
1000个时钟周期,在 DMA传送完成后的中断处理过程需要500个时钟周期,则CPU 用于
硬盘I/O操作的时间百分比大约是多少?
解:硬盘读/写4KB数据需用4KB/4MB=1.024×10-3s≈10~s。为使任何数据不被
错过,每秒钟内须有1/10-3=103次 DMA传送,因此1s内CPU用于在硬盘I/O的时钟周
期数为103×(1000+500)=1.5×10°。因此,CPU用于硬盘I/O的时间占整个CPU 时间
的百分比大约为1.5×10?/(500×10?)=0.3??
DMA方式用于硬盘I/O时,在数据传送期间不消耗任何CPU时钟周期,因此即使硬
盘一直在进行I/O操作,CPU为它服务的时间也仅占0.3??事实上,硬盘在大多数时间内
并不进行数据传送,因此,CPU为硬盘I/O所花费的时间会更少。当然,如果CPU和DMA
控制器同时竞争主存,那么CPU会被延迟与主存交换数据。但通过使用cache,CPU可避
免大多数的访存冲突。因此,通常主存带宽的大部分都可让给外设的DMA传送使用。
3. DMA与存储系统
当采用 DMA方式进行I/O时,存储系统和 CPU 之间的关系会变得更复杂。没有
DMA控制器时,所有对主存的访问都来自CPU,通过MMU中的地址转换和 cache进行访
存。有了 DMA控制器后,系统中就有了另一个访问主存的路径,它不通过地址转换机制和
cache层次。这样,在虚拟存储器和 cache 系统中就会产生一些问题。这些问题的解决通常
要结合硬件和软件两方面的技术支持。
在采用虚拟存储器的系统中,同时有物理地址和虚拟地址,那么DMA是以虚拟地址还
是以物理地址工作呢?很明显,若用虚拟地址,则在 DMA接口中应有一个小的类似页表的
地址映射表,用于将虚拟地址转换为物理地址;若用物理地址,则每次DMA传送不能跨页。
如果一个I/O请求跨页,那么一次请求的一个数据块在送到主存时,就可能不在主存的一
个连续的存储区中,因为每个虚页可以映射到主存的任意一个实页框中,所以多个连续的虚
页不可能正好对应连续的实页框。因此,如果 DMA 采用物理地址,就必须限制所有的
DMA传送都必须在一个页面之内进行,这种情况下,由操作系统把一次传送分解成多次小
数据量传送,以保证每次只限定在一个物理页面内进行。
采用cache的系统中,一个数据项可能会产生两个副本,一个在cache中,一个在主存储
器中,因此,具有DMA控制器的 cache系统也会产生问题。DMA控制器直接向主存储器
发出访存请求而不通过cache,这时,DMA控制器看到的一个主存单元的值与CPU看到的
第8章
303


<!-- page: 321 -->

计算机组成与系统结构(第3版)
304
cache 中的副本可能不同。考虑从磁盘中读一个数据,DMA直接将其送到主存,如果有些
被 DMA写过的单元在 cache中,那么以后CPU读取这些单元的时候,就会得到一个老的
值。类似地,如果 cache采用写回(write back)策略,当一个新的值在 cache 中写入时,这个
值并未被马上写回主存,而此时若DMA直接从主存读,那么读的值可能是老的值。这个问
题称为过时数据问题或1/O一致性问题,其解决方法有以下3种。
第一种解决方式是让1/O活动通过cache进行,这样就保证了在I/O读时能读到最新
的数据,而I/O写时能更新 cache中的任何数据。当然,将所有1/O都通过cache,其代价是
非常大的。因为I/O数据通常很少马上要用到,如果这样的数据把CPU正在使用的有用
数据替换出去,那么就会影响 cache的命中率,给CPU的性能带来很多负面影响。
第二种解决方式是让操作系统在I/O读时有选择地使某些 cache块无效,而在1/O写
时迫使 cache进行一次写回操作,这种操作经常被称为cache刷新,这种方式需要少量硬件
支持。因为大部分cache刷新操作仅发生在DMA数据块访问时,而DMA访问又不经常发
生,所以,如果软件能方便而有效地实现这种方法,则性价比更高。
第三种解决方式是通过一个硬件机制来选择被刷新或使无效的cache项,这种用硬件
来保证 cache一致性的方式大多被用在多处理器系统中。
8.5内核空间 I/O 软件
所有用户程序中提出的1/O请求,最终都是通过系统调用实现的,通过系统调用封装
函数中的陷阱指令转入内核空间的1/O软件执行。内核空间的1/O软件分3个层次,分别
是与设备无关的I/O软件层、设备驱动程序层和中断服务程序层,其中,后两个层次与I/O
硬件密切相关。
8.5.1I/O子系统概述
I/O接口的引入给外设与主机进行信息交换提供了有效“通路”。但是还必须提供一种
手段,让CPU能方便地找到要进行信息交换的设备,并将用户的1/O请求转换成对设备的
控制命令。
现代计算机I/O系统的复杂性一般都隐藏在操作系统中,最终用户或用户程序只需通
过一些简单的命令或系统调用就能使用各种外设,而无须了解设备具体工作细节。
对于最终用户,操作系统通过命令行方式、批命令方式或图形界面方式为最终用户提供
了直接使用计算机资源的手段,用户通过输入相应的命令或操作键盘和鼠标将I/O请求传
递给操作系统。
对于用户程序,所有高级语言运行时系统都提供了执行I/O功能的高级机制,例如,C
语言中提供了像 printf()和 scanf()等这样的标准I/O库函数;C++语言中提供了如<<
(输入)和>>(输出)这样的重载I/O操作符。从通过I/O函数或I/O操作符提出I/O请
求,到1/O设备响应并完成1/O请求,整个过程涉及1/)软件和1/O硬件的协调工作。用
户程序需要从某个设备输入信息或将结果送到外设时,只要通过系统调用(以低级语言方式
提供)或库函数调用(以高级语言方式提供),将I/O请求提交给操作系统即可。
与计算机系统一样,I/O子系统也采用层次结构,图8.26 是I/O 子系统层次结构示


<!-- page: 322 -->

系统互连及输入输出组织
意图。
I/O子系统包含I/O 软件和I/O 硬件两大部
分。I/O 软件包括最上层提出 I/O 请求的用户空
间I/O 软件(称为用户I/O 软件)和在底层操作系
统中对I/O进行具体管理和控制的内核空间I/O
软件(称为系统 I/O 软件),系统 I/O软件又分3个
层次,分别是与设备无关的I/O 软件层、设备驱动
程序层和中断服务程序层。I/O 硬件在操作系统
内核空间I/O软件的控制下完成具体的1/O操作。
用户程序中的I/O请求
用户空间VO软件
运行时系统
与设备无关的/O软件
设备驱动程序
内核空间VO软件
中断服务程序
VO硬件
图8.26 I/O子系统层次结构
操作系统在I/O子系统中承担极其重要的作用,这主要是由I/O子系统的以下3个特
性决定的。
(1)共享性。I/O子系统被多个进程共享,因此必须由操作系统对共享的I/O 资源统
一调度管理,以保证用户程序只能访问自己有权访问的那部分I/O设备或文件,并使系统
的吞吐率达到最佳。
(2)复杂性。I/O设备控制的细节比较复杂,如果由最上层的用户程序直接控制,则会
给广大的应用程序开发者带来麻烦,因而需操作系统提供专门的驱动程序进行控制,应用程
序只需要调用操作系统提供的相应服务例程,而无须了解设备控制的细节,从而简化应用程
序的开发。
(3)异步性。I/O子系统的速度较慢,而且不同设备之间的速度也相差较大,I/O设备
与主机之间的信息交换通常使用异步的中断I/O方式,中断导致从用户态向内核态转移,
因此,I/O处理须在内核态完成,通常由操作系统提供中断服务程序来处理I/O。
用户程序总是通过某种I/O函数或I/O操作符请求I/O操作。例如,用户程序需要读
一个磁盘文件中的记录时,它可以通过调用C语言标准I/O库函数fread(),也可以直接调
用read系统调用的封装函数 read()来提出I/O 请求。不管用户程序中调用的是C库函数
还是系统调用封装函数,最终都是通过操作系统内核提供的系统调用来实现I/O。图8.27
给出了用户程序调用printf()来调出内核提供的 write系统调用的过程。
用户空间、运行在用户态
内核空间、运行在内核态
调用printf)·
用户程序
VO库函数printf()-----封装函数write)-
C语言函数库
write系统调用
内核
图8.27 用户程序、C语言库和内核之间的关系
如图8.27所示,对于一个C语言用户程序,若在某函数中调用了printf(),则在执行到
调用printf()的语句时,便会转到C语言函数库中对应的I/O标准库函数printf()去执行,
而 printf()最终又会转到调用函数write();在执行到调用write()的语句时,便会通过一系
列步骤在内核空间中找到 write对应的系统调用服务例程来执行,从而从用户态转到内核
态执行。
每个系统调用的封装函数会被转换为一组与具体机器架构相关的指令序列,这个指令
序列中,至少有一条陷阱指令,在陷阱指令之前可能还有若干条传送指令用于将I/O操作
第8章
305


<!-- page: 323 -->

计算机组成与系统结构(第3版)
306
的参数送入相应的寄存器。
例如,在1A-32中,陷阱指令就是INTn指令,也称为软中断指令。在早期的IA-32 架
构中,Linux系统将int $0x80指令用作系统调用,在系统调用指令之前会有一串传送指令,
用来将系统调用号等参数传送到相应的寄存器。系统调用号通常在EAX寄存器中,可根
据系统调用号选择执行一个系统调用服务例程。用户进程的I/O请求通过调出操作系统
中相应的系统调用服务例程来实现。
I/O子系统工作的大致过程如下:首先,CPU在用户态执行用户进程,当CPU执行到
系统调用的封装函数对应的指令序列中的陷阱指令时,会从用户态陷入到内核态;转到内核
态执行后,CPU根据陷阱指令执行时EAX寄存器中的系统调用号,选择执行一个相应的系
统调用服务例程;在系统调用服务例程的执行过程中可能需要调用具体设备的驱动程序;在
设备驱动程序执行过程中启动外设工作,外设准备好后发出中断请求,CPU响应中断后,就
调出中断服务程序执行,在中断服务程序中控制主机与设备进行具体的数据交换。
图8.28 是Linux系统中 write 操作的执行过程。
用户空间、运行在用户态
内核空间、运行在内核态
mainO
printf();
orintf)
xxxx();
write()
int $0x80
system_call)
xxxx();
ys_write()
用户程序
printf()标准库函数
write()封装函数
系统调用处理程序系统调用服务例程
图8.28 在Linux系统中 write 操作的执行过程
如图8.28所示,假定用户程序中有一个语句调用了库函数 printf(),在 printf( )函数中
又通过一系列的函数调用,最终转到调用write()函数。在 write()函数对应的指令序列中,
一定有一条用于系统调用的陷阱指令,在IA-32/Linux系统中就是指令 int $0x80 或
sysenter。该陷阱指令执行后,进程就从用户态陷入内核态执行。Linux中有一个系统调用
的统一入口,即系统调用处理程序 system_call()。CPU执行陷阱指令后,便转到 system_
call()的第一条指令执行。在 system_call()中,将根据 EAX寄存器中的系统调用号跳转到
当前系统调用对应的系统调用服务例程 sys_write()去执行。system_call( )执行结束时,从
内核态返回到用户态下的陷阱指令后面一条指令继续执行。
8.5.2与设备无关的I/O软件
一旦通过陷阱指令调出系统调用处理程序(如 Linux中的 system_call)执行,就开始执
行内核空间的I/O软件。首先执行的是与具体设备无关的I/O软件,主要完成所有设备公
共的I/O功能,并向用户层软件提供一个统一的接口。通常,它包括以下几部分:设备驱动
程序统一接口、缓冲处理、错误报告、打开与关闭文件以及逻辑块大小处理等。
1.设备驱动程序统一接口
对于某个外设具体的I/O操作,通常需要通过执行设备驱动程序来完成。而外设的种
类繁多、控制接口不一致,导致不同外设的设备驱动程序千差万别。如果计算机系统中每次


<!-- page: 324 -->

系统互连及输入输出组织
出现一种新的外设,都要为添加新设备的驱动程序而修改操作系统,那么就会给操作系统开
发者和系统用户带来很大的麻烦。
为此,操作系统为所有外设的设备驱动程序规定了一个统一的接口,新设备驱动程序只
要按照统一的接口规范来编制,就可以在不修改操作系统的情况下,在系统中添加新设备驱
动程序并使用新的外设进行I/O。
因为采用了统一的设备驱动程序接口,因而内核中与设备无关的I/O软件包含了所有
外设统一的公共接口中的处理部分。例如,在图8.28所示的Linux系统调用函数执行过程
中,刚陷入内核后所执行的 system_call()函数就是与设备无关的I/O 软件的一部分。
为了简化对外设的处理,在内核高层I/O软件中,将所有外设都抽象成一个文件,设备
名和文件名在形式上没有任何差别,因而被称为设备文件名。内核中与设备无关的I/O 软
件必须将不同的设备名和文件名映射到对应的设备驱动程序。有关文件管理和设备管理的
细节请参看操作系统方面的参考资料。
2.缓冲区处理
用户进程在提出1/O请求时,指定的用来存放I/O数据的缓冲区在用户空间中。例
如,文件读函数fread(buf,size,num,fp)中的缓冲区buf在用户空间中。通过陷阱指令陷入
内核态后,内核通常会在内核空间中再开辟一个或两个缓冲区,这样,在底层I/O软件控制
设备进行I/O操作时,就直接使用内核空间中的缓冲区来存放I/O数据。为何不直接使用
用户空间缓冲区呢?因为,如果直接使用用户空间缓冲区,那么,在外设进行I/O期间,由
于用户进程被挂起而使用户空间的缓冲区所在页面有可能被替换出去,这样就无法获得缓
冲区中的1/O 数据。
每个设备的1/O都需要使用缓冲区,因而缓冲区的申请和管理等处理是所有设备公共
的,可以包含在与设备无关的I/O 软件部分。
此外,为了充分利用数据访问的局部性特点,操作系统通常在内核空间开辟高速缓存,
将大多数最近从块设备读出或写入的数据保存在作为高速缓存的RAM区中。与设备无关
的I/O软件会确定所请求的数据是否已经存在在高速缓存RAM中,如果存在就可能不需
要访问磁盘等外存设备。
3.错误报告
在用户进程中,通常要对所调用的I/O库函数返回的信息进行处理,有时返回的是错
误码。例如,fopen( )函数的返回值为NULL时,表示无法打开指定文件。
虽然很多错误与特定设备相关,必须由对应的设备驱动程序来处理,但是,所有I/O操
作在内核态执行时发生的错误信息,都是通过与设备无关的I/O软件返回给用户进程的,
也就是说错误处理的框架是与设备无关的。
有些错误属于编程错误。例如,请求了某个不可能的I/O操作;写信息到一个输入设
备或从一个输出设备读信息;指定了一个无效的缓冲区地址或者参数;指定了不存在的设备
等。这些错误信息由与设备无关的I/O软件检测出来并直接返回给用户进程,无须再进入
更底层的I/O 软件处理。
还有一类是I/O操作错误,例如,写一个已被破坏的磁盘扇区;打印机缺纸;读一个已
关闭的设备等。这些错误由相应的设备驱动程序检测出来并处理,若驱动程序无法处理,则
驱动程序将错误信息返回给与设备无关的I/O软件,再由与设备无关的I/O软件返回给用
第8章
307


<!-- page: 325 -->

计算机组成与系统结构(第3版)
308
户进程。
4.打开与关闭文件
对设备或文件进行打开或关闭等I/O函数所对应的系统调用,并不涉及具体的I/O操
作,只要直接对RAM中的一些数据结构进行修改即可,这部分工作也是由设备无关的软件
来处理。
5.逻辑块大小的处理
为了为所有的块设备和所有的字符设备分别提供一个统一的抽象视图,以隐藏不同块
设备或不同字符设备之间的差异,与设备无关的I/O软件为所有块设备或所有字符设备设
置了统一的逻辑块大小。例如,对于块设备,不管磁盘扇区和光盘扇区有多大,所有逻辑数
据块的大小相同,这样一来,高层I/O软件就只需要处理简化的抽象设备,从而在高层软件
中简化了数据定位等处理。
8.5.3设备驱动程序
设备驱动程序是与设备相关的1/O软件部分。每个设备驱动程序只处理一种外设或
一类紧密相关的外设。每个外设或每类外设都有一个设备控制器,其中包含各种I/O 端
口。通过执行设备驱动程序,CPU可以向控制端口发送控制命令来启动外设,可以从状态
端口读取状态来了解外设及外设控制器的状态,也可以从数据端口中读取数据或向数据端
口发送数据等。显然,设备驱动程序中包含了许多I/O访问指令,通过执行I/O访问指令,
CPU可以访问设备控制器中的I/O端口,从而控制外设的I/O 操作。
根据设备所采用的I/O控制方式的不同,设备驱动程序的实现方式也不同。
若采用程序直接控制I/O方式,那么设备驱动程序将采用如图8.12所示的处理过程来
控制外设的I/O操作,驱动程序的执行与外设的I/O操作完全串行,驱动程序一直等到全
部完成I/O请求后结束。驱动程序执行完成后,返回到与设备无关的I/O软件层,最后,再
返回到用户进程。这种情况下,请求I/O的用户进程在I/O过程中不会被阻塞,内核空间
的I/O 软件一直代表用户进程在内核态进行I/O处理。
若采用中断控制I/O方式,则设备驱动程序将采用如图8.13(a)所示的处理过程来控
制外设的I/O操作。驱动程序启动第一次 I/O 操作后,将调用处理器调度程序来调出其他
进程执行,而请求I/O的用户进程被阻塞。在CPU执行其他进程的同时,外设进行I/O操
作,此时,CPU和外设并行工作。当外设完成I/O任务时,再向CPU提出中断请求,CPU
检测到中断请求后,会暂停正在执行的其他进程的执行,转到如图8,13(b)所示的一个中断
服务程序去执行,以启动下一次I/O操作。
若采用DMA方式,那么,驱动程序将采用如图8.25所示的处理过程来控制外设的1/O
操作。驱动程序对 DMA控制器进行初始化后,便发送“启动 DMA传送”命令,使设备控制
器控制外设开始进行I/O操作,发送完启动命令后,将执行处理器调度程序,使CPU转去
其他进程执行,而使请求I/O的用户进程阻塞。DMA控制器完成所有I/O任务后,向
CPU发送一个“DMA完成”中断请求信号。CPU在中断服务程序中解除用户进程的阻塞
状态,然后中断返回。
中断控制和 DMA两种I/O方式下,在执行设备驱动程序过程中,都会进行处理器调
度,以使请求I/O的当前用户进程被阻塞;也都会产生中断请求信号,前者由设备在每完成


<!-- page: 326 -->

系统互连及输入输出组织
一个数据的I/O后产生中断请求,后者由DMA控制器在完成整个数据块的I/O后产生中
断请求。因此可见,中断请求是由于执行了设备驱动程序而产生的,外设完成驱动程序要求
的I/O操作后,设备控制器或 DMA控制器会通过中断控制器向CPU发出中断请求,从而
调出中断服务程序执行。
8.5.4中断服务程序
图8.29给出了整个中断过程,包括中断响应和中断处理两个阶段。中断响应是通过
CPU执行中断隐指令来完成的,完全由硬件完成;而中断
处理就是CPU执行一个中断服务程序的过程,完全由软
件完成。虽然不同的中断源对应的中断服务程序不同,但
是,所有中断服务程序的结构是相同的。中断服务程序包
含3个阶段:准备阶段、处理阶段和恢复阶段。
中断响应
关中断、保存断点、
调出某个中断服务程序
中断处理
保护现场和旧屏蔽字
图8.29给出的是多重中断系统下的中断服务程序结
构。从图中可以看出,在保存断点、保护现场和旧的屏蔽
字、设置新屏蔽字的过程中,CPU一直处于“中断禁止”
(“关中断”)状态。CPU 响应中断过程中会关中断,即由
CPU直接将中断允许触发器清零,在进行具体的中断服
务之前,再通过执行“开中断”指令来使中断允许触发器置
设置新屏蔽字
准备阶段
开中断
具体的中断服务
处理阶段
关中断
1,因此,在进行具体的中断服务过程中,若有新的未被屏
蔽的中断请求出现,则CPU可以响应新的中断请求。同
样,在恢复阶段也要让 CPU关中断,并在返回前开中断,
这里开中断和关中断的功能都是通过CPU执行相应的
“开中断”和“关中断”指令实现的。如果在准备阶段和恢
复阶段CPU处在“开中断”状态,那么有可能在断点保
存、现场和屏蔽字的保护和恢复等过程中响应新的中断,
这样,断点或现场及屏蔽字等重要信息就会被新中断破
坏,因而不能回到原来的断点继续执行或因为现场或屏蔽字被破坏而不能正确执行。
恢复现场和旧屏蔽字
清除中断请求
恢复阶段
开中断
返回
图 8.29 中断服务程序的典型结构
图8.29中的“保护现场和旧屏蔽字”和“恢复现场和旧屏蔽字”分别通过“压栈”和“出
栈”指令来实现,“设置新屏蔽字”和“清除中断请求”通过执行I/O访问指令来实现,这些指
令将对可编程中断控制器(PIC)中的中断请求寄存器和中断屏蔽字寄存器进行访问,以使
这些寄存器中相应的位清零或置1。
在设备驱动程序和中断服务程序中使用到的I/O访问指令、“开中断”和“关中断”指令
都是特权指令,只能在操作系统内核程序中使用。
8.6本 章 小 结
所有外设通过相应的电缆连到I/O接口电路上,I/O接口电路再连到系统总线,最终与
CPU和主存相连。各类外设控制器(包括适配器或适配卡)或 DMA控制器、中断控制器等
都属于I/O接口,其职能包括数据缓冲、记录状态、传递命令、转换数据格式等。I/O接口中
第8章
309


<!-- page: 327 -->

计算机组成与系统结构(第3版)
310
通常包含数据缓冲寄存器、状态寄存器和控制寄存器等I/O端口。I/O端口的编址方式有
独立编址和统一编址(存储器映射)两种。
常用I/O控制方式有3种:程序直接控制方式、中断控制方式和DMA方式。程序直
接控制方式分无条件传送和条件传送两种。无条件传送方式下,无须检测接口或设备的状
态,适合于各类巡回检测或过程控制;条件传送(程序查询)方式下,CPU通过查询外设接口
中的“就绪(Ready)”“忙(Busy)”和“完成(Done)”等状态来控制数据的传送,有定时查询和
独占查询两种。程序中断I/O方式下,当外设准备好数据或准备好接收新数据或发生了特
殊事件时,外设通过向CPU发中断请求来使 CPU转到相应的中断服务程序去执行,在中
断服务程序中完成数据交换或处理特殊事件。DMA方式适合像磁盘一类的高速设备以成
批方式和主存直接交换数据。首先,要对 DMA控制器进行初始化;然后由 DMA控制器控
制总线在主存和高速设备之间进行直接数据交换;最后,DMA控制器发出“DMA传送结
束”信号给外设接口,由外设接口发中断请求给 CPU,CPU 进行 DMA结束处理。
I/O子系统包含I/O软件和1/O硬件两大部分。I/O 软件包括最上层提出1/O 请求
的用户空间I/O软件和在底层操作系统中对I/O进行具体管理和控制的内核空间I/O 软
件。系统I/O软件又分3个层次,分別是与设备无关的I/O软件层、设备驱动程序层和中
断服务程序层。1/O硬件在驱动程序的控制下完成具体的I/O 操作。
习题
1.给出以下概念的解释说明。
字符型设備
块传递设备
键盘扫描码
I/O 接口
1/O 控制器
1/O 端口
命令端口
数据端口
状態端口
1/O空間
独立编址
统一编址
存储器映射1/O
I/O 指令
程序查询方式
就绪状態
中断控制方式
可屏蔽中断
不可屏蔽中断
中断屏蔽字
中断响应优先级
中断处理优先级DMA 方式
周期挪用
DMA 控制器
2.简单回答下列问题。
(1)什么是I/O接口?I/O接口的基本功能有哪些?
(2)串行接口和并行接口的特点各是什么?
(3)CPU如何进行设备的寻址?1/O端口的编址方式有哪两种?各有何特点?
(4)什么是程序查询1/O方式?说明其工作原理。
(5)什么是中断控制I/O方式?说明其工作原理。
(6)什么是向量中断?说明在向量中断方式下形成中断向量的基本方法。
(7)为什么中断控制器把中断请求设备标识(中断类型)放在总线的数据线上,而不是放在地址线上?
(8)在多周期处理器中并不是每个时钟周期结束都允许响应中断,为什么?如果在一条指令执行过程
中,CPU 响应中断而转去执行中断服务程序,会产生什么问题?
(9)什么是可屏蔽中断?什么是不可屏蔽中断?
(10)为什么在保护现场和恢复现场的过程中,CPU必须关中断?
(11)DMA方式能够提高成批数据交换效率的主要原因何在?
(12)CPU 响应 DMA请求和响应中断请求有什么区別?
(13)在 DMA接口中,什么时候给出“DMA请求”(或“总线请求”)信号?什么时候给出“中断请求”信
号?CPU在什么时候响应 DMA请求?在什么时候响应中断请求?


<!-- page: 328 -->

系统互连及输入输出组织
3.假定采用独立编址方式对1/O端口进行编号,那么必须为处理器设计哪些指令来专门用于进行
1/O端口的访问?连接处理器的总线必须提供哪些控制信号来表明访问的是1/O空间?
4.假定主存和磁盘存储器之间连接的同步总线具有以下特性:支持4字块和16字块两种长度(字长
32位)的突发传送,总线时钟频率为200MHz,总线宽度为64位,每个64位数据的传送需1个时钟周期,
向主存发送一个地址需要1个时钟周期,每个总线事务之间有2个空闲时钟周期。若访问主存时最初4个
字的存取时间为200ns,随后每存取一个四字的时间是20ns,磁盘的数据传输率为5MB/s,则在4字块和
16字块两种传输方式下,该总线上分别最多可有多少个磁盘同时进行传输?
5.假设有一个磁盘,每面有200个磁道,每个盘面总存储容量为1.6MB,磁盘旋转一周时间为25ms,
每道有4个区,每两个区之间有一个间隙,磁头通过每个间隙需1.25ms。请问:从该磁盘上读取数据时的
最大数据传输率是多少(单位为B/s)?假如有人为该磁盘设计了一个与计算机之间的接口,如下图所示,
磁盘每读出一位,串行送入一个移位寄存器,每当移满16位后向处理器发出一个请求交换数据的信号。
在处理器响应该请求信号并读取移位寄存器内容的同时,磁盘继续读出一位一位数据并串行送入移位寄
存器,如此继续工作。已知处理器在接到请求交换的信号以后,最长响应时间是3μs,这样设计的接口能否
正确工作?若不能则应如何改进?
区4
区1
区3`
区2
磁盘读入-
16位移位寄存器
6.假设某计算机带有20个终端同时工作,在运行用户程序的同时,能接收来自任意一个终端输入的
字符信息,并将字符回送显示。每一个终端的键盘输入部分有一个数据缓冲寄存器 RDBR(i=1~20),当
在键盘上按下某一个键时,相应的字符代码即进入RDBR,并使它的“完成”状态标志Done(i=1~20)置
1.要等处理器把该字符代码取走后,Done,标志才置0。每个终端显示(或打印)输出部分也有一个数码缓
冲寄存器 TDBR,(i=1~20),并有一个 Ready,(i=1~20)状态标志,该状态标志为1时,表示相应的
TDBR,是空着的,准备接收新的输出字符代码,当TDBR,接收了一个字符代码后,Ready,标志才置0,并
将字符代码送到终端显示。为了接收终端的输入信息,处理器为每个终端设计了一个指针PTR(i=1~
20)指向为该终端保留的主存输人缓冲区。处理器采用下列两种方案输入键盘代码,同时回送显示。
(1)每隔一固定时间T转入一个状态检查程序DEVCHC,顺序地检查全部终端是否有任何键盘信息
输入,如果有,则顺序完成之。
(2)允许任何有键盘信息输入的终端向处理器发出中断请求。全部终端采用共同的向量地址,利用它
使处理器在响应中断后,转入一个中断服务程序DEVINT,由后者查询各终端状态标志,并为最先遇到的
请求中断的终端服务,然后转向用户程序。
要求画出 DEVCHC和 DEVINT 两个程序的流程图。
7.某计算机CPU主频为500MHz,所连接的某外设最大数据传输率为20KB/s,该外设接口中有一个
16位的数据缓存器,相应的中断服务程序执行时间为500个时钟周期,是否可以用中断方式进行该外设的
输入输出?假定该外设的最大数据传输率改为2MB/s,是否可以用中断方式进行该外设的输入输出?
8.若某计算机有5个中断源1#、2#、3#、4#、5#,中断响应优先级为1#>2#>3#>4#>5#,
而中断处理优先级为1#>4#>5#>2#>3#。要求:
(1)设计各中断源对应的中断屏蔽字(假设0为屏蔽,1为开放)。
(2)若在运行主程序时,同时出现2#、4#中断请求,在处理2#中断过程中,又同时出现1#、3#,5#
中断请求,试画出CPU的运行过程示意图。
第8章
311