01、什么是DMA
📢本篇将带领大家深刻理解DMA
。
一、什么是DMA
DMA(直接内存访问)是一种技术,可以让数据在内存和设备之间直接传输,而不需要CPU全程参与。比如在读取硬盘文件或处理网络数据时,DMA就像一个智能搬运工,能自动把数据从一个存储区域搬到另一个区域,比如从硬盘直接送到内存里,或者在内存的不同位置之间搬移。
这样做的好处是,CPU不用一直盯着数据搬运这种重复性工作,可以腾出手来处理更重要的任务。比如当你用手机听歌时,DMA负责把歌曲文件从存储芯片传到内存,而CPU可以同时处理屏幕显示、触控操作等其他事情,这样手机就不会因为传输音乐文件而卡顿。
二、原理介绍
DMA(直接内存访问)就是让数据在不需要CPU参与的情况下直接传输。具体来说:
- 基本要素:
- 需要明确数据来源地址(源)
- 需要明确数据目的地地址(目标)
- 需要设定传输的数据量
- 传输类型共有四种:
- 外部设备 → 内存
- 内存 → 外部设备
- 内存 → 另一块内存
- 外部设备 → 另一个外部设备
- 工作原理:
- DMA控制器会临时接管电脑内部的"数据通道"(总线)
- 这个接管权限是CPU"授权"给DMA的
- 数据传输完成后,DMA会主动通知CPU:"任务完成了,你可以收回控制权了"
简单来说,DMA就像快递公司的智能分拣系统——CPU只需要告诉它"从哪里运什么到哪里",之后运输过程就完全自动化了,最后再通知CPU任务完成。这样CPU就能腾出手来做更重要的事情。
三、传输过程
DMA传输分为四个步骤:
1️⃣ DMA请求
- 开启DMA功能(打开时钟)
- 设置数据传输的起点地址(内存地址)和终点地址(设备地址)
- 定义要传输的数据量(如多少字节)
- 设置传输方向(内存→设备或设备→内存)、优先级(高/低)、数据块大小(字节/字/双字)
- 开启中断功能,并通知设备准备就绪
2️⃣ DMA响应
- DMA控制器检查当前是否有更高优先级任务被占用
- 向总线控制器申请接管总线使用权
- 等待CPU完成当前操作后释放总线控制权
- 确认获得总线使用权后,通知设备开始传输
3️⃣ DMA传输
- DMA控制器直接控制总线
- 数据在内存和外设之间自动传输(完全不经过CPU)
- 每次传输后自动更新地址指针和剩余计数
4️⃣ DMA结束
- 数据传输完成后释放总线控制权归还CPU
- 通知设备停止工作
- 触发中断信号唤醒CPU
- CPU处理后续操作(如检查传输结果或准备新任务)
整个过程就像快递运输:
设备(寄件人)提出需求 → 物流中心(DMA)申请运输通道 → 占用道路(总线)运送货物 → 送达后通知收件人并告知快递公司任务完成。
四、DMA导致的问题
DMA在提升效率的同时,也带来了数据同步问题。比如:
问题场景:
CPU在处理数据时,会先把数据存在"缓存"里(就像临时记事本),处理完再慢慢写回内存。
如果这时DMA(比如外设)突然要读取或写入同一块内存,就会出问题:
- DMA读到的是CPU还没写回的旧数据
- 或者DMA写入新数据后,CPU还在用旧缓存里的旧数据
解决方法: 需要让CPU和DMA的数据保持一致。有两种常用方案:
1️⃣ 一致性DMA(安全但慢)
原理:直接禁用缓存
- 把DMA用的内存区域标记为"不缓存"(就像告诉CPU:"这块内存别用记事本,直接操作真实内存")
- 申请内存时,系统会从预先留好的专用DMA内存池分配(比如设备树里设置的区域)
- 优点:简单可靠,全程数据一致
- 缺点:牺牲速度(因为不用缓存了),且占用内存资源时间长(通常从设备初始化一直保留到退出)
2️⃣ 流式DMA(灵活但复杂)
原理:动态刷新缓存
允许用普通内存(比如
- 写数据给DMA前:强制CPU把缓存里的修改刷新到内存(回写)
- DMA写完后:告诉CPU缓存的内容已过期,下次要用得重新从内存读(失效)
优点:速度快(能用缓存),内存灵活(可临时使用任意内存)
缺点:需要程序员仔细管理数据流向(比如明确告诉系统数据是"CPU→DMA"还是"DMA→CPU")
现代处理器(如ARM)可能有自动辅助功能(比如ACP),能自动处理部分同步,让操作更简单
总结对比:
一致性DMA | 流式DMA | |
---|---|---|
缓存处理 | 直接禁用缓存(全程不缓存) | 动态刷新/失效(保留缓存) |
内存来源 | 系统专用DMA内存池 | 普通内存(如kmalloc ) |
生命周期 | 长期占用(驱动整个生命周期) | 短期临时使用 |
性能 | 较慢(不用缓存) | 较快(合理用缓存) |
复杂度 | 简单(无需手动同步) | 复杂(需管理数据流向) |