文章目录
- 第一章 各有千秋
- 一、轮询 (Polling)
- 二、中断 (Interrupt)
- 三、DMA (Direct Memory Access)
- 四、差异对比
- 五、总结
第一章 各有千秋
本文章结合实际应用的经验,查询书籍和网络资料汇总,欢迎补充完善。
在计算机体系结构和数据通信系统中,CPU 与外部设备(如网卡、串口、磁盘、传感器等)之间的数据交互,主要有三种控制方式:轮询、中断和 DMA。它们的本质区别在于 CPU 参与数据传输的程度和时机,从而带来不同的效率、实时性和适用场景。
一、轮询 (Polling)
轮询是一种程序直接控制的 I/O 方式。CPU 主动、周期性地检查外设的状态寄存器,判断设备是否需要服务(如“数据就绪”或“发送完成”),一旦条件满足就执行数据读写。
1、工作流程: 1)CPU 从外设的状态端口读取标志位。 2)若设备未就绪,则跳回步骤 1 继续检查(忙等待)。 3)若设备就绪,CPU 执行数据传输(如读取接收缓冲器)。 4)传输完成,返回主程序或继续下一次查询。
2、技术特点 1)实现简单:纯软件逻辑,无需额外硬件支持。 2)CPU 利用率低:查询期间 CPU 被完全占用做无意义的“忙等待”,不能处理其他任务。 3)响应时间可预测:最差延迟由轮询周期决定,属于同步检测模式。 4)易丢失数据:如果查询间隔大于外设的数据到达间隔,会发生溢出。 5)数据易被打断:若嵌入式中存在多个中断,设计不当容易被其他的中断打断传输。
3、适用场景:简单单任务系统、设备状态变化缓慢或通信速率极低、且 CPU 没有其他事务需要处理的场合。
4、举个例子:单任务系统通过轮询串口接收字节,CPU 循环检测 RXNE 标志,一旦置位立刻读取。
二、中断 (Interrupt)
中断是一种事件驱动的异步机制。外设通过硬件信号主动向 CPU 发起服务请求,CPU 暂停当前程序,转而执行与该设备对应的中断服务程序(ISR),完成数据传输后再返回原任务。
1、工作流程 1)外设满足条件(如收到一字节)时,通过中断控制器向 CPU 发出中断请求(IRQ)。 2)CPU 完成当前指令,检查中断使能与优先级,响应中断。 3)硬件自动保存部分上下文(PC、状态寄存器),进入 ISR。 4)ISR 执行必要的数据搬移、清除中断标志等操作,该过程应尽量简短。 5)执行中断返回指令,恢复现场,继续原程序。 不同的指导教材流程略有区别,大致流程类似。
2、特点 1)CPU 利用率高:设备未就绪时 CPU 可以执行其他任务,仅在需要服务时才切换,避免了忙等。 2)响应异步事件快:相比轮询,能在事件发生的瞬间得到处理,实时性好。 3)存在上下文切换开销:保存/恢复寄存器、中断延迟(中断屏蔽、优先级排队)会消耗时间。 4)高频中断会压垮 CPU:当数据速率极高时,频繁中断会导致“中断风暴”,CPU 大量时间花在进出 ISR 上,有效吞吐反而下降。
3、使用场景:适合低、中速异步事件:键盘、鼠标、串口单字节接收、定时器等。在多线程和多中断系统中,注意线程和中断优先级配置。
4、举个例子:传统以太网卡每收到一个数据包产生一次中断,由驱动 ISR 将数据从网卡 FIFO 复制到协议栈缓冲区。
三、DMA (Direct Memory Access)
DMA 是一种让专用控制器接管总线、在后台自动完成数据块搬运的技术。CPU 仅负责初始化传输参数,之后整个数据块在外设与内存之间(或内存到内存)的移动完全由 DMA 控制器负责,不再需要 CPU 逐字干预。
1、工作流程 1)CPU 配置 DMA 控制器:源地址、目的地址、传输长度、传输模式(单次/循环)等。 2)外设准备就绪(或软件触发),DMA 控制器向总线仲裁器请求总线控制权。 3)获得总线后,DMA 控制器发起读写周期,将外设数据读入内部寄存器,再写入内存,源/目的地址自动递增。 4)重复步骤 3 直到传输计数归零,DMA 释放总线,向 CPU 发出一个 DMA 完成中断。 5)CPU 在中断中得知传输完成,进行后续处理(如通知应用程序数据已就绪)。
2、传输模式 1)单字节/周期挪用:DMA 每传一字节释放一次总线,让 CPU 有机会执行,减少 CPU 停顿。 2)块传输:连续传输整块数据后再释放总线,效率高但会长时间占用总线。 3)散聚模式:支持非物理连续的内存区域,用链表描述符链接多段传输。
3、技术特点 1)CPU 负担最小化:CPU 只参与传输的首尾,适合大批量、高速数据传输。 2)传输速度快:专用硬件进行地址计算和时序控制,效率远高于 CPU 逐字搬移。 3)需额外硬件和总线仲裁:设计复杂,DMA 与 CPU 对总线的竞争可能引入微小的访存延迟。
4、适合高速块设备:磁盘读写、网络数据包大缓冲、显示帧缓冲刷新、高速 ADC/DAC 连续采样流。
下面是DMA工作流程的时序交互图,清晰地展示CPU、DMA控制器、外设和总线之间的交互过程:
内存
外设
总线
DMA控制器
CPU
内存
外设
总线
DMA控制器
CPU
#mermaid-svg-mjnHnf7XqIZmEoLi{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mjnHnf7XqIZmEoLi .error-icon{fill:#552222;}#mermaid-svg-mjnHnf7XqIZmEoLi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mjnHnf7XqIZmEoLi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mjnHnf7XqIZmEoLi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mjnHnf7XqIZmEoLi .marker.cross{stroke:#333333;}#mermaid-svg-mjnHnf7XqIZmEoLi svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mjnHnf7XqIZmEoLi p{margin:0;}#mermaid-svg-mjnHnf7XqIZmEoLi .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mjnHnf7XqIZmEoLi text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mjnHnf7XqIZmEoLi .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-mjnHnf7XqIZmEoLi .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-mjnHnf7XqIZmEoLi #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-mjnHnf7XqIZmEoLi .sequenceNumber{fill:white;}#mermaid-svg-mjnHnf7XqIZmEoLi #sequencenumber{fill:#333;}#mermaid-svg-mjnHnf7XqIZmEoLi #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-mjnHnf7XqIZmEoLi .messageText{fill:#333;stroke:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mjnHnf7XqIZmEoLi .labelText,#mermaid-svg-mjnHnf7XqIZmEoLi .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .loopText,#mermaid-svg-mjnHnf7XqIZmEoLi .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mjnHnf7XqIZmEoLi .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-mjnHnf7XqIZmEoLi .noteText,#mermaid-svg-mjnHnf7XqIZmEoLi .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-mjnHnf7XqIZmEoLi .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mjnHnf7XqIZmEoLi .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mjnHnf7XqIZmEoLi .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mjnHnf7XqIZmEoLi .actorPopupMenu{position:absolute;}#mermaid-svg-mjnHnf7XqIZmEoLi .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-mjnHnf7XqIZmEoLi .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mjnHnf7XqIZmEoLi .actor-man circle,#mermaid-svg-mjnHnf7XqIZmEoLi line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-mjnHnf7XqIZmEoLi :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
1. 初始化阶段
2. 传输准备
3. 总线请求与获取
4. 数据传输阶段
地址自动递增
loop
[直到传输计数归零]
5. 释放总线
6. 完成通知
7. 后续处理
配置传输参数
(源地址、目的地址、长度、模式)
数据准备就绪/触发信号
请求总线控制权
授予总线控制权
读取数据
返回数据
写入数据
释放总线控制权
发送DMA完成中断
中断处理程序
通知应用程序数据就绪
该流程图展示了DMA工作流程的完整时序:
四、差异对比
下表展示三种I/O控制方式的差异。:
| 启动方式 | CPU 主动查询 | 外设异步请求 | CPU 初始化,DMA 控制器自动搬运 |
| CPU 干预时机 | 全程干预,逐个数据查询和搬运 | 仅响应中断后处理数据 | 仅初始化和传输完成时介入 |
| CPU 利用率 | 极低(忙等待) | 高(仅在服务时切换) | 最高(传输期间 CPU 可完全释放) |
| 响应速度 | 取决于查询频率,可能延迟或丢失 | 很快,有中断延迟但实时性好 | 批量传输,单个字节无立即响应 |
| 数据传输粒度 | 通常单字节/字 | 通常少量数据(ISR 要求短小) | 块数据,几十到几千字节或更大 |
| 软硬件开销 | 软件查询开销小,无额外硬件 | 硬件中断控制器,上下文切换开销 | 需 DMA 控制器,总线仲裁开销 |
五、总结
实际高性能通信系统很少单一使用某一种方式,而是将它们结合起来以平衡吞吐量和 CPU 负载:
1、中断 + DMA:网卡、磁盘控制器中,DMA 负责批量数据搬运,传输完成后产生一次中断通知 CPU 取走整块数据,避免逐字节中断。
2、中断 + 轮询 (NAPI):先用中断通知有数据到来,随后关闭中断,改用轮询方式持续收割数据包,当一段时间无包时再重新开启中断。这样在高负载下避免了频繁中断,低负载下保留了中断的及时性。
实际工程中若有其他结合情况,欢迎交流!
以上就是该章内容,在设计协议栈或驱动时,需要根据数据速率、延迟容忍度、CPU 预算和硬件特性来精准选择或组合这三种传输机制,才能在性能与资源之间找到最佳平衡。
后期使用理论和代码实践的方式对每种方式展开讲述。






