
1. 为什么CPU会被I/O操作拖垮程序查询与中断方式的固有短板聊到计算机组成原理里的I/O控制方式大部分人在复习初期都会有个困惑明明CPU那么快为什么还要专门设计一套DMA机制来传送数据直接让CPU来搬不就行了这个困惑非常正常因为你还没意识到I/O设备的速度和CPU不是一个量级如果让CPU亲自下场搬运数据整台机器的性能会被外设硬生生拖到蜗牛模式。先看最简单的程序查询方式。它的逻辑很直白CPU不断去读取I/O设备的状态寄存器看看设备有没有准备好准备好了就传一个数据没准备好就继续等。问题出在继续等这三个字上。CPU和磁盘、网卡这类外设的速度差距动辄几个数量级外设准备一个数据可能要几百微秒而CPU一个时钟周期才几纳秒。在查询方式下CPU几乎把所有时间都花在盯着状态位上别说干别的活了连计算任务都得停摆。这种方式适合极其简单的场景比如单片机上读个按键状态但在现代计算机里基本属于自杀式设计。程序中断方式比查询方式进步了一大截核心思路是没事别烦我有事再喊我。CPU发起I/O后继续执行主程序外设准备好数据后发出中断请求CPU响应中断、暂停当前工作去处理数据传送。听起来很合理对吧但这里藏着一个关键问题每次中断只能传送一个字节或一个字。如果要从磁盘读一个128KB的数据块按每个字16位来算就意味着要发生六万多次中断。每一次中断都有现场保护、断点保存、中断服务程序执行、恢复现场这一整套流程光是中断响应的开销就远远超过了数据传送本身。我用个不太严谨但很好懂的比例中断方式相当于你正在写论文快递员每隔几百米给你打一次电话让你下楼取一个小包裹取完之后你重新集中精力写两分钟又有个新包裹到货。一上午下来论文没写几行快递倒是取了几百趟。正因为在查询和中断这两种方式下CPU要么全程被占用、要么被高频打断DMADirect Memory Access直接存储器存取方式才被设计出来。它的核心价值只有一句话在数据块传送阶段让CPU彻底撒手不管由DMA控制器直接接管总线在内存和外设之间批量搬运数据只在开始和结束时跟CPU打个招呼。注意这里是传送阶段让CPU撒手不是全程撒手这两个字的差别后面我会专门讲因为这是408里最著名的坑之一。讲到这儿我相信你已经理解DMA解决的痛点了它把CPU从一个字节一个字节的传送任务中解放出来让CPU专心做计算把搬运这种体力活交给专门的硬件去干。说白了DMA控制器就是一个专职搬家公司而CPU是公司老板老板只需要告诉搬家公司把哪个仓库的东西搬到哪栋楼然后继续开自己的会就行搬完公司会打电话汇报成果。2. 拆解DMA控制器它凭什么能绕过CPU搬数据DMA能绕过CPU不代表它没有大脑恰恰相反DMA控制器本身就是一块相当复杂的硬件逻辑电路它的大脑由一组精心设计的寄存器和一个状态机组成。408考试中关于DMA方式的很多辨析题本质上都是在考你对这套寄存器工作流程的理解程度。2.1 DMA控制器的内部构成逐个寄存器看职责一块典型的DMA控制器至少包含以下核心部件主存地址寄存器MAR存放当前要读写的主存单元地址。每次传送一个数据后MAR自动加1或者减1指向下一个内存单元。它决定了数据搬到内存的哪个位置。外设地址寄存器DAR存放I/O设备的设备码或地址信息告诉DMA控制器数据从哪个外设来、要到哪个外设去。比如磁盘控制器通过它来选择是读磁盘的哪个扇区。传送字节计数器WC记录还需要传送多少个字节或字。每传一个数据WC减1减到0就代表这一批数据全部传送完毕。这个计数器是后处理阶段判断是否结束的关键依据。控制与状态寄存器CSR存放控制命令和状态标志比如DMA请求标志、传送方向内存到外设还是外设到内存、允许中断标志等。中断机构当WC计数到0时DMA控制器会向CPU发出中断请求通知它传送完毕该做善后工作了。看到这个寄存器清单你应该能反应过来一件事DMA控制器本质上是一个能独立执行搬运循环的小型处理器。CPU在预处理阶段要做的就是往MAR、DAR、WC这几个寄存器里填入参数配置好传送方向和启动信号——这一步相当于把搬家地址、要搬多少箱货、用车还是用船这些信息交代给搬家公司。之后DMA控制器就按照自己的状态机节奏一轮一轮地完成从外设读数据→写入内存或反向→修改MAR和WC这个循环根本不需要CPU再指手画脚。2.2 一次DMA传送的全过程拆成前中后三个阶段DMA传送不是从头到尾都由DMA控制器独干它实际上分三个阶段每个阶段的主角都不一样预处理阶段CPU主导CPU执行I/O指令向DMA控制器写入起始主存地址到MAR、设备地址到DAR、传送字节数到WC并启动DMA传送命令。这个阶段非常短但对正确性至关重要——任何参数填写错误后面整块数据都会写错地方。数据传送阶段DMA控制器主导DMA控制器检测到外设准备好一个数据块不是单个字节后向CPU发出总线请求信号通常叫HRQ或BUSREQ获得总线使用权后开始控制数据在外设和主存之间直接流动。每传送一个数据单元MAR加1WC减1直到WC为零。这个阶段CPU完全不知道细节它可以继续执行自己的程序只要别去访问DMA正在占用总线所涉及的内存区域就行。后处理阶段CPU再次参与WC归零后DMA控制器通过中断机构向CPU发出中断请求CPU响应后执行中断服务程序做数据校验、判断传送是否正确、决定是否继续下一批传送等工作。注意这里用到的中断和程序中断方式里的中断完全是两码事程序中断方式的中断是为了传送每一个字节而DMA后处理的这个中断是为了通知一批数据传送完毕。讲到这里我想把一段容易被误解的表述说清楚。很多人看完教材会记成DMA的整个传送过程不需要CPU介入这句话严格来说是错的。准确表述应该是数据传送阶段不需要CPU介入但预处理需要CPU写寄存器后处理需要CPU响应中断做校验。408的判断题和选择题特别喜欢在整个传送过程完全不需要CPU这些措辞上做文章每次考试都能收割一大批粗心考生。2.3 数据到底从哪里走到哪里不经过CPU的传送路径DMA方式传输数据的数据通路和查询/中断方式也有本质区别。中断方式下数据的搬运是CPU通过读外设数据寄存器→写内存这两条指令完成的数据物理上经过了CPU内部的寄存器而DMA方式下数据直接从外设接口的数据缓冲寄存器经过系统总线写入主存或者反向流动CPU被完全绕开。这一点值得你画个图记牢外设 ↔ DMA控制器 ↔ 系统总线 ↔ 主存CPU不在这个数据通路上。这个特性带来了两个重要推论一是数据传送速度不再受限于CPU的取指、译码、执行周期而是受限于总线和存储器的带宽所以DMA能实现微秒级甚至更高速度的块传送二是CPU的寄存器不会被数据搬运过程占用它可以在DMA干活的同时继续算自己的东西——这也是DMA和另外两种方式的根本区别所在。3. DMA与CPU的访存冲突三种仲裁策略的取舍逻辑DMA控制器要搬数据必然要访问主存而CPU也要访问主存取指令、读写数据都算总线是共享资源两边同时用就会撞车。怎么调解这个矛盾教材上给出了三种经典策略408对这个点的考查频率非常高而且往往以给你一个场景让你选出最优/最差方案的形式出现所以不仅要记住名称还要理解每种策略背后的代价。3.1 停止CPU访问主存简单粗暴的独占式传送第一种策略是当DMA需要传送数据时它在获得总线控制权后强制CPU暂停对主存的访问直到这一整批数据全部传送完毕才把总线还给CPU。优点控制逻辑最简单DMA传送期间总线完全由它掌握传送速率可以拉到最高也不会出现DMA和CPU交替申请总线带来的频繁切换开销。缺点CPU被强制放假的时间太长了。如果传送一个1MB的数据块DMA可能要连续占用总线几百微秒甚至几毫秒这段时间CPU连指令都取不到相当于整机运算能力直接归零。对一些实时性要求高的场景比如CPU正在处理网络协议栈这种断供是灾难性的。所以这个策略只适合外设传送速率极高、且DMA传送频率较低的场合。在DPA动态随机存储器的刷新和某些老式磁盘控制器的设计中比较常见但现代通用计算机已经很少直接采用整块传送的纯停止方式了。3.2 周期挪用周期窃取见缝插针的夹缝生存第二种策略叫周期挪用也叫周期窃取。它的思路是DMA控制器每传送一个数据字就向CPU借用一个主存存储周期用完立刻归还总线CPU接着跑自己的程序。如果恰好CPU此刻没在访问主存比如它正在做内部运算DMA就白白捡了一个周期的便宜如果CPU正在访存DMA就需要等一个周期再插入。优点CPU的停顿时间被压缩到一个存储周期级别对CPU整体性能的影响比停止访问方式小得多。而且DMA可以充分利用CPU不访存的间隙来搬运数据主存的带宽利用率更高。缺点每传送一个字都要申请一次总线、使用一个周期、然后再释放反复的申请和归还带来额外的控制开销。另外如果DMA请求比较频繁CPU和DMA之间会形成你争我抢的局面可能出现某个设备在规定时间内抢不到周期的情况。周期挪用在目前大多数微机系统的磁盘DMA和网卡DMA中都有应用因为它兼顾了传送效率和对CPU的友好性。3.3 交替访存硬件上最奢侈的解决方案第三种策略是把主存的每个存储周期一分为二前半周期固定给CPU访问后半周期固定给DMA访问。这样两边谁都不用申请、谁也不用等待天然就不存在冲突。优点CPU和DMA在时间上没有互相等待对CPU的打扰几乎可以忽略不计DMA也能获得稳定的传输带宽非常适合那些需要实时、恒定速率的外设比如某些数据采集设备。缺点代价非常明显——主存的有效访问速度被打折了。本来一个存储周期可以完成一次完整的读写现在为了错开CPU和DMA要求存储器的实际工作频率翻倍才能保证两边都获得足够的带宽这对存储器硬件提出了很高的要求。所以这种策略一般只在对实时性极其严苛的专用系统里才会出现普通个人电脑里用不上这么奢侈的配置。为了区分清楚我做个表放这儿复习的时候可以直接对着看仲裁策略CPU受干扰程度传送速率硬件复杂度适用场景停止CPU访存大整批传送期间挂起最高低大批量高速突发传送周期挪用小仅挪用单周期较高中常见微机磁盘/网卡DMA交替访存几乎无稳定但受限于存储器频率高实时数据采集等专用场景我自己的体会是考场上如果遇到哪个策略最好之类的问法一定要先看清题干描述的外设类型和传送场景。没有绝对的好坏只有匹配不匹配。比如题目说设备要求不定期地传送少量数据且不希望CPU被长时间占用那选周期挪用大概率没问题但如果题目强调设备传送速率极高且数据块很大停止CPU访存可能是更合理的选项因为周期挪用频繁切换反而吃不消。4. 408高頻真题考法DMA与中断的对比以及四个常见丢分点DMA方式在408试卷里从来不是孤零零的知识点它几乎每次都会和程序中断方式放在一起考对比。我在带学生复习的时候反复强调一句话中断方式和DMA方式不是并列的对立物而是中断机制在DMA后处理阶段仍然会被用到这种包含关系。很多同学做题做错就是栽在把两者当成完全对立的选择题选项上。4.1 一张表讲透中断方式与DMA方式的五大区别对比维度程序中断方式DMA方式数据传送单位字节或字数据块数据传送执行者CPU执行中断服务程序来搬DMA控制器直接控制总线搬响应时机指令执行周期的末尾响应中断请求在存储周期结束后响应总线请求每条总线周期结束即可介入CPU的干预程度每传一个字节/字都要CPU全程参与仅在预处理和后处理阶段需要CPU参与数据传送阶段不需要并行性传送和CPU计算无法真正并行传送与CPU计算可以并行注意表格里的响应时机这一行这里是高频考点中的隐藏考点。中断请求的响应发生在一条指令执行完毕后的中断响应周期也就是说CPU必须等到当前指令完整执行完才能处理中断而DMA的总线请求响应更灵活它只要求在当前存储周期结束后就能介入总线。这意味着DMA的响应速度比中断响应更快、更即时。为什么因为中断响应要保护现场、保存断点、跳转到中断服务程序这一整套流程必须和指令边界对齐而DMA只需要在总线层面做交接和指令执行过程完全解耦自然可以做到更细粒度的时间点介入。4.2 注意DMA结束后也要发中断这是应该的有同学容易产生一个错误印象DMA和中断是互斥的用了DMA就不能再用中断。事实恰恰相反——DMA数据块传送完毕DMA控制器正是通过发送中断请求把这个事件告知CPU的。也就是说一次完整的DMA传输流程里中断机制反而出现在了最后的善后环节。这个逻辑需要理顺CPU写寄存器启动DMADMA控制器批量搬运数据搬运过程中CPU忙自己的事搬运完毕DMA控制器向CPU发出中断请求CPU响应中断执行后处理校验数据、决定后续动作。所以真正准确的说法是DMA方式用中断通知CPU传送完成但不会像程序中断方式那样用中断来逐字逐字节地传送数据。考题如果表述成DMA完全取代了中断那是错误的表述成DMA传送结束时会发出中断请求这是对的。4.3 四个最容易丢分的模糊表述结合多年讲题经验我把最容易让考生丢分的几种说法整理出来你要是能把这几条全部判断正确DMA这块基本就稳了DMA方式传输过程中CPU完全不需要参与——错。数据传送阶段不需要CPU参与但预处理和后处理阶段需要CPU配合。DMA比中断方式的传送速度快所以DMA可以替代中断——错。DMA的快体现在数据块传送不需要CPU逐字执行指令但DMA本身的工作还要依赖中断机制来善后二者是配合关系而非替代关系。由于DMA传送数据的单位是块因此DMA只能用于块设备如磁盘不能用于字符设备——错。磁盘确实是最典型的DMA应用场景但网卡每次接收的是一个数据帧/包本质上也是块和数据采集设备同样可以通过DMA来搬运数据。字符设备的低速数据流有时也能通过DMA汇总成块来处理。严格说DMA更适合成批数据交换的场景但不能把它和磁盘划等号。DMA控制器和CPU都能访问主存所以它们可以同时访问主存中的同一单元——错。同一时刻总线上只有一个设备可以获得控制权二者访问的是不同的地址单元还勉强能通过交替访存实现访问同一单元则必然冲突除非存储体做了多体交叉设计。这些模糊点背后其实是同一个思维误区把硬件机制想象得太理想化或者太极端化。实际硬件设计中几乎没有哪种机制是绝对免费的DMA省去了CPU逐字搬运的负担但代价是引入了总线仲裁和访存冲突处理的复杂度。408考这个知识点本质上就是考你有没有理解这种用硬件复杂度换取CPU解放的工程权衡思想。5. DMA在真实机器里的身影从磁盘到网卡再到显卡学了知识不谈应用总感觉飘在半空。如果你在准备408我强烈建议你在理解DMA原理之后抬头看看自己手头正在用的这台电脑——DMA其实无处不在只是你平时看不见它。最经典的例子是磁盘控制器。你从硬盘读一个几MB的文件操作系统不会傻到让CPU一个字节一个字节地去磁盘控制器的缓冲区里扒数据而是把目标内存地址、要读的扇区数、起始扇区号这些参数交给磁盘控制器上的DMA逻辑然后磁盘控制器通过DMA方式把数据整块整块地搬到内存里。等你需要用到这些数据的时候数据已经安安稳稳躺在内存里了。你感受到的文件秒开背后可能就有DMA的功劳。网卡同样高度依赖DMA。一次网络数据包到达网卡网卡先把数据收进自己的FIFO缓冲区然后通过DMA把数据直接写入内存中的内核缓冲区通常是驱动预先分配好的一段内存用DMA描述符来管理地址和长度。CPU只需要在DMA完成后收到一次中断接着在网络协议栈里继续处理这个包。如果没有DMA千兆网卡每秒要产生上百万次中断CPU早就被淹没在中断风暴里了。显卡其实也用了类似的思路不过它的主要方向是GPU从显存读取渲染数据以及CPU把纹理数据通过DMA批量上传到显存。图形学里常说的DMA纹理上传异步传递本质上就是在用DMA方式让CPU和GPU之间的数据搬运不阻塞渲染线程。如果你以后接触Linux驱动开发会更频繁地看到DMA的痕迹。比如dma_alloc_coherent、dma_map_single这类接口就是为了在驱动里分配一块DMA能够直接访问的内存缓冲区而DMA描述符descriptor的概念就是上面说的把地址和长度告诉DMA控制器的具体实现。可以说你理解了408教材上这套DMA原理再看驱动代码里那些可疑的寄存器写操作思路会清晰很多。6. 复习DMA方式的落地建议记忆主线与一个管用的类比最后聊点应试和学习的实操心得。DMA这个知识点虽然重要但它不是孤立的一个点而是成网状的——上承存储器的访问原理下接中断系统左右并联着I/O控制方式的另外两种方案。我建议你复习时按照一条主线去串主线CPU为什么撒手动机→ 撒手后谁接管DMA控制器→ 接管时怎么和CPU共享总线三种仲裁策略→ 干完活怎么交代后处理中断→ 在哪些设备上真这么干磁盘/网卡/显卡。这条线走通了DMA的来龙去脉就完整了考试无论从哪个角度切入你都能快速定位到它考的是这条线上的哪个环节。至于记忆技巧我常用的一个类比是DMA就像你去餐馆点了一桌菜点单预处理时你把菜单、桌号、忌口交代给服务员上菜数据传送过程中你该聊天聊天该玩手机玩手机不用去后厨盯着菜全部上齐传送完毕服务员喊你一声您的菜齐了后处理中断你确认一下有没有上错菜就可以开吃了。这个类比把三个阶段的分工和CPU的参与程度说得特别清楚每次讲到这儿学生都会说哦原来如此。最后再分享一个小细节做题时看到DMA传送结束后的中断要判断它属于内中断异常还是外中断。DMA控制器发出的中断请求来自硬件外部事件因此归类为外中断而不是CPU内部执行指令产生的内中断。这个分类在选择题里也出现过别看它小丢分的人可不少。希望这篇拆解能帮你把DMA这块硬骨头啃得更透408里这套I/O控制方式的分数扎实拿住。