操作系统I/O系统复习指南:从设备控制到磁盘调度 1. 为什么I/O系统在操作系统课程里最像大杂烩很多同学复习操作系统时第一章进程管理还能背得头头是道第五章虚拟存储器也能画出页面置换的流程一到了第六章输入输出系统就开始犯迷糊。这种感觉很正常因为I/O系统这一章的知识点覆盖范围实在太杂了既涉及硬件电路设备控制器、寄存器、中断控制器又涉及内核软件策略设备驱动程序、中断处理程序、缓冲管理、设备分配最后还得处理磁盘、键盘、打印机这些五花八门的物理设备。对比下来进程管理是在讲怎么管CPU内存管理是在讲怎么管内存而I/O系统必须同时回答三个问题怎么和硬件打交道、怎么给上层应用提供统一接口、怎么让慢速设备和高速CPU之间配合得尽量高效。先说个我复习时的直观感受进程管理用到的是队列、状态转移、调度算法这类内容有清晰的流程图背起来很有安全感但I/O系统里你面对的是设备控制器里一组寄存器、CPU与设备的四种控制方式、中断处理流程中的保存现场和恢复现场、缓冲池里的所有队列……每一个点都能单独拿出去考一道简答题组合在一起就成了让人摸不着头脑的大杂烩。这篇文章就把这盘杂烩按线索拆开先讲硬件底子再讲控制方式的演进逻辑接着讲软件层次和缓冲、设备分配、SPOOLing最后落到磁盘调度算法。照着这条线捋完期末复习和考研大题都不成问题。如果你正在准备操作系统期末或者考研复习这篇内容基本就是第六章复习地图如果你已经工作了想在遇到I/O瓶颈或者排查设备异常时有个系统性的知识框架这篇同样适用。我会尽量用实际场景来讲而不是照搬教材目录。2. 硬件层先把概念捋清设备、控制器、寄存器与中断2.1 设备分类的两种维度别只知道块设备和字符设备教材第一件事就是给设备分类最常见的是分成块设备和字符设备。块设备以数据块为单位传输典型的像磁盘、SSD特点是传输速率高、可寻址也就是说我可以直接访问第N块数据不需要从头扫字符设备以字节为单位传输典型的像键盘、串口、打印机特点是逐字节处理不可寻址你没法让打印机跳到第100个字符再开始打。但这个分类并不是绝对的。比如USB设备你说它是块设备还是字符设备其实USB本身是传输总线上面可以挂U盘块设备也可以挂鼠标字符设备。所以考试问某设备属于什么类型时要强调的是设备的访问方式而不是接口类型。还有一个容易踩的点网络接口卡网卡既不是块设备也不是字符设备它只能按报文传输教材里通常会单独把它列出来叫做网络接口设备。复习时别漏了它选择题经常出。按使用方式来分也有意义独占设备打印机、磁带机、共享设备磁盘、虚拟设备通过SPOOLing技术模拟出来的独占设备。这三种分类方式是后续设备分配算法的基础建议直接对照着记独占设备靠分配、共享设备靠管理、虚拟设备靠SPOOLing技术。2.2 设备控制器是CPU和设备的翻译官CPU不可能直接控制一台打印机或者一块磁盘中间必须有一个设备控制器也叫I/O控制器它的作用可以理解为翻译官CPU发指令给控制器控制器把指令翻译成设备能懂的信号再控制设备执行。每个设备控制器都配有几个寄存器用来和CPU沟通数据寄存器CPU和设备之间往来的数据暂存地。比如读取磁盘时控制器先把磁盘里读出的数据放进数据寄存器CPU需要时再过来取。状态寄存器记录设备当前状态比如空闲忙碌出错数据就绪。CPU可以通过读状态寄存器判断操作是否完成。控制寄存器CPU用来给控制器下达命令的比如启动读写复位设备设置参数。很多教材在这一块会顺带提到底部编址和独立编址两种方式。所谓独立编址就是设备寄存器的地址和内存地址是两套地址空间CPU需要通过专门的I/O指令来访问而内存映射I/O也叫统一编址是把设备寄存器直接编入内存地址空间CPU用普通访存指令就能操作它们。考试常问内存映射I/O的好处答案要点是无需专门I/O指令、对设备的操作和访存统一、保护机制可以复用。这个知识点不复杂但容易忽略值得记一下。2.3 中断机制让CPU从死等中解脱出来假设你是CPU让打印机打印一份文件然后你怎么办如果只能死盯着打印机看它有没有打完那CPU就废了。中断机制解决的就是这个问题CPU发出I/O请求后可以继续干别的活设备完成操作时控制器往CPU的中断请求线INTR上发一个信号CPU在每条指令执行结束后都会检查中断信号一旦发现就转入中断处理程序。中断处理的流程是期末高频考点我建议按五步记忆第一步设备控制器向CPU发中断信号第二步CPU保存当前程序的现场程序计数器、寄存器状态、程序状态字压入系统栈第三步根据中断向量找到对应的中断处理程序入口第四步处理程序执行真正的I/O收尾工作第五步恢复现场CPU回到被打断的程序继续执行。考试如果出中断处理过程中谁保存现场这种细节题标准答案是CPU硬件负责保存程序计数器、程序状态字中断处理程序负责保存其他通用寄存器的现场。设备控制器在中断请求发出后就不再干预了。另外有个名词叫中断向量其实就是一张表每个中断源对应一个表项表项里存放着该中断处理程序的内存起始地址。CPU接到中断信号后靠中断号去查这张表找到入口地址跳转过去。把这套机制理解成点外卖就行你CPU下单后继续打游戏外卖小哥设备到了会打电话中断信号你根据电话判断是哪个外卖中断向量然后下楼取餐执行中断处理回来继续打游戏恢复现场。3. 四种I/O控制方式从死等到全自动本质是CPU逐步放权3.1 程序直接控制方式CPU亲自盯着最原始的方式是程序直接控制方式也叫忙等或轮询。CPU向设备控制器发出I/O命令后就一直循环读取状态寄存器反复问好了没好了没直到设备状态变成已完成。这种方式最大的问题就是CPU被完全占用设备工作期间CPU什么活都干不了。虽然实现简单一套循环就能搞定但在现代系统里几乎不会用因为代价太高。教材里讲它主要是作为后续优化思路的反面起点。复习时记住它的核心特征就够了CPU和设备串行工作一次只能做一件事效率极低。3.2 中断驱动方式不用死等但每传一个字节打扰一次中断驱动方式让CPU从死等状态里解放出来CPU发出I/O请求后立刻返回执行其他程序设备完成数据准备后发中断通知CPU来取。以键盘输入为例用户每敲一个键键盘控制器就发一次中断CPU中断当前程序把按键数据从数据寄存器读走存入内存缓冲区然后再恢复现场继续执行。看起来比轮询好多了但问题在于每次传输一个字节就要触发一次中断CPU频繁保存现场恢复现场大量时间耗在中断处理本身。你可以想象一个程序要读1MB数据磁盘每准备好一个扇区的数据就发一次中断CPU就得中断495次、切换现场495次。这个开销依然很大。所以中断驱动方式适合字符设备、对速率要求不高的场合但用来做高速块设备传输还是有瓶颈。3.3 DMA方式数据搬运不再需要CPU亲力亲为DMA直接存储器访问方式的出现核心变化是在内存和高速设备之间开辟了一条直达通道数据搬运工作交由DMA控制器完成CPU只在开始和结束时介入。具体来说CPU需要告诉DMA控制器三样东西数据在内存中的起始地址、要传输的数据长度、操作方向是读还是写。然后CPU就干别的去了DMA控制器负责逐块搬运数据每搬完一块内存地址递增、计数器递减等全部搬完才向CPU发一次中断通知我搞定了。这里有个高频考点DMA方式和中断驱动方式的区别。核心差异在传输单位——中断驱动是每次一个字节就打断一次CPUDMA方式是整块数据连续搬运全程不打扰CPU只在全部完成时发一次中断。所以DMA显著减少了CPU的干预次数适合磁盘等高速块设备。还有个小知识点是DMA的周期窃用DMA控制器要往内存写数据时需要占用系统总线而CPU此刻可能也要用总线这就存在总线冲突。DMA采用窃用内存周期的方式即在CPU不使用总线的间隙把数据写入内存。因为CPU大部分指令都不直接用到总线所以冲突概率不高对CPU整体性能影响远小于逐字节中断。3.4 通道方式一个独立的I/O处理器到了通道方式变化就更大了。通道不是简单的控制器而是自带指令系统的I/O处理器能自己执行通道程序。CPU只需要发一条启动通道的指令通道就会去执行事先编好的通道程序完成一组I/O操作包括设备寻址、数据传送、格式转换等全部独立完成CPU完全不用管等通道完成后发一个中断告诉CPU任务结束。对比一下DMA方式下DMA控制器每次只能完成一个固定方向的、简单的数据块搬运任务而且它的工作模式是被CPU配置好参数后执行通道方式下通道CPU自己有一套指令可以执行复杂的I/O控制序列用一条通道指令就能控制多台设备、完成多次传输。换句话说DMA是一台只能干搬砖活的专用控制器通道是一台能执行程序的微型处理器。考试中问你通道与DMA的区别这就是标准答法。这四种控制方式其实是一条CPU逐步放权的演进线程序直接控制方式CPU全程盯着中断驱动方式CPU被频繁打断但可以间接触手DMA方式CPU只负责开头和结尾通道方式CPU只需要发一次指令剩下的全交给通道。把这条主线记住了时序图和优缺点基本都能推导出来。4. I/O软件层次设备驱动、中断处理与设备独立性的分工逻辑4.1 用户层、设备独立层、设备驱动层、中断处理层教材常把I/O软件组织成四层结构从上到下分别是用户层软件、设备独立性软件、设备驱动程序、中断处理程序。各层各司其职上层不需要知道下层实现细节这也是分层设计的好处上层发号施令下层干事干活。用户层软件最简单直观就是应用程序里调用的那些库函数比如C语言的printf、fread或者高级语言里的文件操作接口。这些库函数会发起系统调用把用户请求转发到下层的设备独立性软件。设备独立性软件是这一层里最值得多看两眼的。它的核心思想是用户在访问设备时使用的是逻辑设备名比如打印机叫lp0而不是直接指定物理设备。用户层发请求时不需要知道这台打印机到底是惠普的还是佳能的设备独立性软件负责建立逻辑设备到物理设备的映射关系并统一调用驱动程序的接口。它做的事情包括设备命名与映射、设备保护、给用户进程分配和回收设备、屏蔽设备类型差异、提供块大小统一的视图、缓冲管理等。总之它就是用户和真实驱动之间的翻译缓冲层。设备驱动程序就非常物化了。每一类设备对应一个驱动它知道如何操作这类设备的寄存器、如何发起设备命令、如何与设备控制器交互。比如printf最终会把输出重定向到驱动程序驱动程序再去操作显卡或终端控制器的寄存器把字符显示出来。设备驱动是操作系统内核里和硬件打交道的唯一代言人也是出错率比较高的部分驱动的Bug会导致系统蓝屏、设备无响应。中断处理程序在四个层次里最贴近硬件。它负责响应设备发来的中断信号读取设备状态、把数据从寄存器搬走或者唤醒来等待该I/O完成的进程。被中断打断后的现场保存、恢复由硬件和操作系统配合完成这是中断处理的底层基础。4.2 设备独立性带来的实际好处用户态不用关心硬件差异很多初学者会问为什么要搞这么多层直接让用户程序操作设备寄存器不好吗答案很简单安全性和可移植性。如果每个用户程序都可以直接操作硬件寄存器整个系统很快就会乱套一个程序写错一个寄存器可能把其他程序的设备操作全搞崩。而且不同厂商的设备细节天差地别如果程序员每换一个品牌就要重写一遍程序软件生态就完了。设备独立性把设备长什么样这件事隔离在了驱动层上层全部用统一接口。你在Linux下写一个文件写入操作无论底层是SSD、机械硬盘还是U盘本质上走的是同一套write()系统调用路径只是最终会派发给对应设备的驱动程序。这就是我说的隔离变化、统一接口也是分层设计里最值得体会的一个思想。举个蛮常见的例子你在应用程序里用printf打印日志日志可能输出到屏幕也可能重定向到文件还可以通过管道传给另一个程序。用户层代码完全无感知这就是设备独立性的力量——输出目标对用户程序透明用户程序只需要面向逻辑设备展开工作。4.3 设备驱动的调用链从系统调用到最终硬件操作复习I/O软件层次时画一下完整调用链会特别清楚。拿Linux下的read()举例用户程序调用read(fd, buf, count)通过库函数陷入内核发起系统调用内核根据文件描述符fd找到对应的文件对象和设备节点经由虚拟文件系统VFS分发到具体文件系统文件系统层判断要访问的设备调用块设备驱动的通用接口块设备驱动把请求转换成设备控制器能理解的命令写入控制器寄存器控制器执行操作完成后通过中断通知CPU中断处理程序接管唤醒等待的进程数据从设备控制器拷贝到用户缓冲区用户进程继续执行read()返回读到的字节数。能不能把这个链条背下来很关键因为不管是期末考试还是面试只要问到读磁盘的过程考的都是这个链路。还有一个小细节read()返回前通常还有一次从内核缓冲区向用户缓冲区的拷贝。这个拷贝和后面的缓冲技术在逻辑上有直接关系。5. 缓冲与设备分配解决速度不匹配和资源争抢问题的三板斧5.1 缓冲技术为什么无处不在CPU快、设备慢中间必须有个蓄水池CPU处理速度以纳秒为单位键盘每秒只能产生几十个字节磁盘虽然快但和CPU相比依然是数量级的差距。如果每次I/O都让CPU等着设备慢慢传时间全浪费在路上。缓冲区的本质就是蓄水池数据先从设备批量读入缓冲区CPU有空时再从缓冲区取反过来CPU要输出数据时先写入缓冲区攒批设备再慢慢从缓冲区取走去执行。单缓冲、双缓冲、环形缓冲、缓冲池是四级递进关系。单缓冲最简单设备和CPU之间只有一个缓冲区设备读一块数据放进去CPU取走然后再放下一块。问题在于设备和CPU对同一个缓冲区的使用必须串行CPU在取数据时设备不能往缓冲区里写反之亦然。双缓冲等于有两个缓冲区交替使用设备往缓冲区A写的同时CPU可以从缓冲区B读两边各用各的不冲突。不过双缓冲依然有流水线停顿的可能——如果设备写满A的速度比CPU消耗B的速度快CPU还没用完B设备就已经写完A等着了。环形缓冲适用于生产者和消费者的速率不完全对称的场合。在内存里开一块连续的环形区域生产者和消费者各持一个指针生产者按顺时针填充消费者按顺时针取走两个指针之间的部分就是当前缓冲区里有效的数据。环形缓冲的问题在于满空两种状态的判断容易出歧义需要额外用一个计数器来记录当前有效数据量。教材常考这个很多同学会栽在为什么反对指针相遇就判断为空或满上想清楚生产者追上消费者就是满消费者追上生产者就是空但这两者在物理上长得一样就能理解了。缓冲池是更通用的方案把内存中多个缓冲区统一管理形成一组队列。空闲缓冲区挂在一个空闲队列上装满输入数据的缓冲区挂在输入队列上装满输出数据的缓冲区挂在输出队列上。系统运行时根据用户进程的请求动态分配缓冲区用完了再归还到相应队列。理解缓冲池的关键就是队列管理它比固定单/双缓冲灵活得多也是Linux内核中比较常见的设计思路。5.2 设备分配算法和安全检查别让进程占着茅坑不拉屎设备分配解决的是谁先用、用多久、用完还给谁的问题。设备分配表里有设备表和控制表核心记录两类信息设备是否被占用、等待该设备的进程队列。分配时系统先检查设备状态空闲就分配给进程不空闲就把进程挂进该设备的等待队列。考试中常见的分配原则有两类先来先服务按进程请求设备的先后排队和优先级高者优先高优先级进程可以插队。分配方式上要注意静态分配和动态分配的区别静态分配在进程运行前一次性分配所有需要的设备运行期间不放回简单但浪费严重动态分配按需分配、用完即还效率高但可能出现死锁。关于死锁教材里通常会讲安全分配方式一个进程只能同时占有一个设备如果要申请第二个设备必须先释放第一个。这种方式从根源上杜绝了两个进程各占一个设备又互相等待对方设备的死锁条件但代价是设备利用率下降。复习时如果考一道设备分配时如何避免死锁答出破坏请求和保持条件要求进程一次申请所有资源或者用完即还就行。5.3 SPOOLing技术把独占设备变成共享设备SPOOLing假脱机技术是第六章最有意思的部分因为它用一种巧妙的方式把独占设备模拟成了共享设备。最早的计算机没有磁盘打印这种独占设备只能一台机器同时服务一个作业其他作业必须干等。后来人们引入了磁盘作为缓冲介质SPOOLing的核心就是进程要打印时系统并不直接把打印机分给进程而是把打印数据先写入磁盘上的打印缓冲区一个专门目录然后打印机后台程序按顺序取出数据送给打印机打印。这样一来对每个用户进程来说它感觉自己独占了一台打印机——因为它只需要往缓冲区写数据不需要等待真正的打印机空闲。而真正的打印机被SPOOLing程序管理按序服务所有进程的打印任务。用户们感觉独占实际共享这就叫虚拟设备。操作系统课本里经典的例子是共享打印机和共享输入设备比如扫描任务批量处理。考试常考SPOOLing的组成我总结为三块输入井/输出井磁盘上的缓冲区域、输入进程/输出进程负责排队和调度、内存缓冲区。另外SPOOLing技术的好处要写成三点提高了I/O速度数据先落到磁盘不需要等慢速物理设备、将独占设备改造为共享设备、实现了虚拟设备的概念。在我实操过的Linux系统中打印队列CUPS就是这么干的你提交一个打印任务它先进入队列打印机空闲时再取出来打印完全就是SPOOLing思想的现代版本。6. 磁盘调度算法第六章最容易拿分的部分6.1 先看基础磁盘的读写时间由什么构成硬盘要读一个扇区的数据总共耗时大致等于寻道时间旋转延迟时间传输时间。寻道时间是磁头从当前磁道移动到目标磁道的时间这部分时间最长也是调度算法主要优化的对象旋转延迟是等待目标扇区旋转到磁头下面所用的时间平均约为转半圈的时间传输时间是真正读取数据的时间。顺序访问和随机访问的差距就来自寻道时间和旋转延迟。这个差距极其惊人——机械硬盘随机读写的性能表现远差于顺序读写这和后面的调度算法优劣密切相关。现代SSD没有寻道和旋转的物理限制但底层调度思想依然有参考价值毕竟很多教材的题目还是在机械硬盘模型下讨论。6.2 四大调度算法对比FCFS、SSTF、SCAN、C-SCAN这些算法真要记起来不难难的是做题时别绕晕。我按自己的习惯总结成了一张对比表复习时建议自己也画一份算法核心策略优点缺点适用场景FCFS先来先服务完全按请求到达顺序服务公平、实现简单寻道距离可能很大效率低请求少且均匀时可用SSTF最短寻道时间优先每次选择离当前磁头最近的请求平均寻道时间较短可能饿死远处请求偏向局部请求集中时效率高SCAN电梯算法磁头沿一个方向移动到达最远端后反向避免饥饿寻道性能稳定最远端请求等待时间较长应用最广泛C-SCAN循环扫描单向移动服务到达最远端后快速回起点重新开始等待时间更均匀需要快速回程回程不服务请求对等待时间均匀性要求高的系统做调度算法题最容易错的两个地方一是SCAN算法里磁头方向的变化时机——不是没有请求了就反向而是到达了最远端的请求后才反向二是C-SCAN里回程不处理请求这一点经常被忽略题目特意把回程路上有请求的磁道写出来就是陷阱。建议做题时先把磁头运动方向画在纸上再逐条按时间推进不容易错。6.3 N-Step-SCAN和FSCAN对电梯算法的两个小修补有了SCAN的基础还有两个改进算法值得知道N-Step-SCAN和FSCAN。N-Step-SCAN的思想是分批次处理把请求按到达时间分成若干批每次SCAN只处理一批内的请求处理过程中新到的请求留到下一批。这样做的好处是避免磁头被连续涌入的请求拽着走防止某个方向的请求一直插队导致其他方向的请求长期等待。FSCAN就更简单了只把当前时刻已经存在的请求交给一次SCAN处理处理期间新来的请求都放入另一队列下次再处理。本质上它和N-Step-SCAN是同一思路的不同实现。这两个算法不常考大题但选择题偶尔出现核心是理解分批隔离的思想避免新旧请求互相干扰。6.4 实操视角Linux下I/O调度器怎么选如果你用的是Linux磁盘I/O调度器的算法选择其实是这套理论的落地版。老内核2.6时代默认的调度器是CFQ完全公平队列会按进程分组排队保证公平性后来的deadline调度器按请求截止时间排序保证每个请求不会等太久再到NVMe SSD时代内核开始默认用none也就是完全交给硬件队列操作系统层面几乎不调度。实操上的经验是机械硬盘建议保留deadline或者BFQ能明显减少大文件读写时的卡顿SSD且跑数据库这类高并发随机读写时用none直接走硬件多队列效果更好因为软件层调度反而成了瓶颈。你可以用cat /sys/block/sda/queue/scheduler查看当前调度器用echo deadline /sys/block/sda/queue/scheduler临时切换。这个知识点考研不一定考但工作后特别实用。我看到有些刚工作的同学在Linux服务器上跑数据库发现延迟特别高一查调度器还在用BFQ换成none之后延迟直接下来一半原理就是绕过软件层的排队策略让SSD原生多队列自己干活。7. 期末实操与备考避开这章的常见坑7.1 刷题时高频出现的细节陷阱第六章的知识点以零散著称做题时经常栽在一些不起眼的细节上。我总结了几个典型的坑对照着自查一下中断驱动方式和DMA方式的分界线中断驱动是每次传输一个单位字节/字就打断CPU一次DMA是整块传输结束后才打断CPU一次。如果题干说到数据块为单位进行传输传输完成后才发中断那就不是普通中断驱动方式而是DMA方式很多选择题的干扰项就在这里。设备控制器的寄存器访问方式如果题目问操作系统访问设备寄存器时使用普通访存指令对应的术语是内存映射I/O或统一编址而不是独立编址。独立编址是使用专用I/O指令两者千万别搞反。缓冲技术的计算题单缓冲处理一块数据的总时间约等于设备传送时间CPU处理时间两者串行双缓冲里如果设备传送时间和CPU处理时间大致相等总时间约等于设备传送时间CPU处理时间中的较大者再加一点启动开销。考试中最常见的题型是给出设备传输速率和CPU处理一块数据的时间让你求吞吐量本质考的就是串行还是并行。SCAN算法的方向题目如果没说初始方向一般默认磁头当前正在移动的方向就是服务方向如果题目有明确的磁头位置和历史比如当前位于53号磁道正在向磁道号增大的方向移动就严格按照该方向走到底再反向。SPOOLing技术是共享打印机而不是独占打印机打印进程之间看到的逻辑设备是独立的但物理上只有一台打印机把它理解为虚拟设备技术最准确。通道和DMA的区别凡出现通道程序小型CPU独立指令系统这些描述答案一定是通道方式凡出现内存起始地址传输长度方向参数这种CPU配置一次就搬一块数据的答案是DMA方式。7.2 实操练习的建议动手写一个中断处理流程光背概念是不够的第六章有一道经典实操题写一个模拟的中断处理流程用伪代码描述从设备发出中断到CPU恢复现场的全过程。我建议每个人都动笔写一遍不要求真实汇编用文字流程也行。写完再对照标准流程基本能发现自己遗漏的点是现场保存的细节或者中断向量的查找。如果有Linux环境可以再看两个真实场景一是cat /proc/interrupts能看到系统中每个中断号被触发的次数直观理解中断向量和具体设备绑定二是dmesg | grep -i dma看看硬盘DMA相关的日志信息能在实操层面加深对DMA机制的理解。这一步算是给学习加点真实感很多同学就是靠这些命令把抽象概念落到实际的。7.3 和前后章节的联动I/O这章和进程调度、内存管理的关系最后一层要打通的是章节之间的联动。I/O系统不是孤立的它和时间片轮转、虚拟内存、进程调度都有关系。比如一个进程发起read()系统调用后会阻塞在等待队列里直到数据就绪才被唤醒这其实就是进程管理里的阻塞与唤醒机制缓冲区中的数据拷贝涉及用户态和内核态地址空间的切换这是内存管理里用户空间与内核空间的典型应用磁盘调度算法和内存管理中的页面置换算法思路也很像都是优化访问顺序、减少代价的策略。如果你在复习时能把I/O这一章和进程管理、内存管理的知识点串起来看会发现操作系统的整体架构其实就是一个复杂的资源调度系统CPU要调度内存要调度设备也要调度。第六章的主角其实就是设备资源的调度理解了这一点再回头看设备分配、缓冲池、磁盘调度整个思路就顺畅了。我在实际学习中最深的体会是I/O系统确实杂但杂不等于乱它有一条非常清晰的从硬件到软件、从底层到上层的线索。只要把硬件设备、控制器、中断、DMA、通道连成一条硬件支撑链再把设备独立性软件、驱动、中断处理程序连成一条软件处理链两条链子搭在一起整章的内容就都能装进脑子里。复习的时候试着往这两条链子上挂知识点比孤立地背定义要高效得多。