深入理解 Linux DMA-BUF 子系统:设计思想、UML 类图与同步机制
本文按《深入理解 Linux pinctrl 子系统》的同一框架重构 DMA-BUF 子系统:先讲设计思想,再按 Consumer(Importer)→ Core(dma-buf)→ Provider(Exporter / Heap / Fence)自上而下展开;关键类统一用 UML 类图描述,并说明类与成员职责;最后给出逻辑漏洞与修正清单。
1. DMA-BUF 子系统设计思想
1.1 它要解决的核心问题
DMA-BUF 是 Linux 内核里用于跨设备、跨进程共享内存缓冲区的核心框架。它看起来只是"共享一块内存",但一旦进入内核,就会遇到八类复杂问题:
- 跨设备共享:GPU 分配的内存要给显示控制器、视频编解码器、NPU、摄像头同时使用。
- 跨进程传递:一个进程分配的缓冲区要传给另一个进程,传统共享内存做不到设备级语义。
- 零拷贝:数据不能在各设备间复制,必须共享同一块物理内存。
- DMA 映射差异:不同设备有不同的 DMA 地址空间、IOMMU 映射、cache 属性。
- 同步:谁在用、谁在写、何时可复用,必须有 fence 语义。
- CPU 访问一致性:CPU 与设备访问同一块内存,cache 必须同步。
- 生命周期:缓冲区被多个设备、多个进程引用,释放时机必须精确。
- 分配策略差异:system / CMA / VRAM / SRAM,不同内存类型的分配方式完全不同。
DMA-BUF 的使命,就是用 fd 即句柄 + Exporter/Importer 分离 + fence 同步 三件套,把这些全部收口到 drivers/dma-buf/。
1.2 三个平面:用户态 → Core → Exporter/Importer
DMA-BUF 的顶层设计是三层:
text
用户态:ioctl(/dev/dma_heap/*) 分配,ioctl(dmabuf_fd) 同步,SCM_RIGHTS 传 fd
│
▼
Core 层:dma-buf.c 维护 dma_buf 生命周期、attach/map、ioctl、poll
dma-fence.c / dma-resv.c 提供同步
dma-heap.c 提供分配框架
│
▼
Exporter / Importer:
Exporter 实现 dma_buf_ops,负责底层内存
Importer 通过 dma_buf_attachment 建立自己的 DMA 映射
- 用户态 :通过
/dev/dma_heap/*分配,通过DMA_BUF_IOCTL_SYNC同步。 - Core :
dma-buf.c、dma-fence.c、dma-resv.c、dma-heap.c。 - Exporter:DRM GPU/VPU/VOP、ION、v4l2、Rockchip 各类驱动。
- Importer:DRM 显示控制器、V4L2、视频编解码、NPU、DMA 控制器。
1.3 核心抽象:dma_buf / dma_buf_ops / dma_buf_attachment
DMA-BUF 最有价值的抽象是三个:
| 抽象 | 归属 | 语义 | 谁在用 |
|---|---|---|---|
dma_buf |
Core | 共享缓冲对象,挂在 anon file 上 | 所有方 |
dma_buf_ops |
Exporter | 内存分配/映射/释放回调表 | Exporter |
dma_buf_attachment |
Importer | "设备↔缓冲"关系,含 sg_table | Importer |
三者关系:
text
dma_buf ──1:N──► dma_buf_attachment ──1:1──► sg_table
│
└──.ops──► dma_buf_ops
设计原则:
Exporter 定义内存,Core 管生命周期,Importer 拿映射。三者解耦,任意一方变化不影响另外两方。
1.4 fd 即句柄(Handle-Body 分离)
struct dma_buf 内部挂在一个 anon file 上:
dma_buf->file指向struct file;- 用
dma_buf_fd()安装 fd; - 用
dma_buf_get(fd)/dma_buf_put()做引用计数; get_dma_buf()=get_file(),复用文件引用计数机制。
关键优势:
- fd 可以跨进程用
SCM_RIGHTS传递; - fd 可以
mmap、poll、dup; - fd 的生命周期由 VFS 统一管理。
1.5 attach / map 两阶段分离
DMA-BUF 把"建立关系"和"建立映射"分开:
dma_buf_attach()/dma_buf_dynamic_attach():建立"设备↔缓冲区"关系;dma_buf_map_attachment():为该设备真正建立 DMA 映射,返回sg_table;- 映射可缓存:
cache_sgt_mapping。
设计动机:
- 同一缓冲区可被多个设备以不同方式映射;
- Importer 可以在 attach 时做准备工作,在 map 时真正配置 IOMMU;
- 支持动态映射(
dma_buf_dynamic_attach+importer_ops->move_notify)。
1.6 同步靠 fence + reservation
DMA-BUF 的同步机制分两层:
dma_fence:表达"某个时间线(context)上的 seqno 何时完成":
context:时间线 id,全局唯一;seqno:时间线内的序号;cb_list:完成回调链表;error:错误码。
dma_resv:每个 dma_buf 的"预定对象":
fence_excl:独占 fence(写者);fence:共享 fence 表(读者);ww_mutex:更新侧锁,防多锁死锁;seqcount:RCU 读侧一致性。
设计动机:
- 写者等待所有读者完成;
- 读者等待写者完成;
- 多锁顺序用 ww_mutex 统一。
1.7 CPU 访问与缓存一致性契约
DMA-BUF 明确 CPU 访问的契约:
dma_buf_begin_cpu_access():访问前,Exporter 负责 pin / cache flush;dma_buf_end_cpu_access():访问后,Exporter 负责 cache invalidate;mmap得到的映射是"incoherent"的;- 用户态需用
DMA_BUF_IOCTL_SYNC包裹 CPU 访问。
关键点:
DMA-BUF 不保证 cache 一致性,由 Exporter 与 Importer 共同遵守契约。
1.8 与其它子系统的关系
| 子系统 | 交互 |
|---|---|
| DRM / KMS | GPU 分配 framebuffer,显示控制器 importer |
| V4L2 | 摄像头 exporter,编解码器 importer |
| IOMMU | Importer 通过 IOMMU 映射 sg_table |
| DMA engine | 通过 dma-buf 直接做设备间 DMA |
| 用户态 | /dev/dma_heap/*、/dev/sw_sync、sync_file |
| Rockchip | dma-buf-cache、rk_cma_heap 扩展 |
1.9 设计原则总结
- fd 即句柄:跨进程传递,VFS 统一管理。
- Exporter/Importer 分离:内存与使用解耦。
- attach / map 两阶段:关系与映射分离。
- fence 同步:时间线 + seqno,跨设备通用。
- reservation 簿记:独占/共享 fence 表,ww_mutex 防死锁。
- CPU 访问契约:begin/end_cpu_access 包裹。
- 分配策略可插拔:dma-heap 工厂模式。
2. 总体架构:自上而下看 DMA-BUF
2.1 框架图
text
┌───────────────────────────────────────────────────────────────────────────────┐
│ 用户态 (userspace) │
│ ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC/SET_NAME/GET_FLAGS/GET_UUID) │
│ ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC) → 返回 dma-buf fd │
│ fd 传递 (SCM_RIGHTS) / mmap() / poll() │
└───────────────┬───────────────────────────────────────────────┬───────────────┘
│ /dev/dma_heap/* │ 共享 fd
▼ │
┌───────────────────────────────┐ │
│ dma-heap 分配框架 dma-heap.c │ │
│ (dma_heap_ops 工厂) │ │
│ heaps/: system/cma/rk_cma/... │ │
└───────────────┬───────────────┘ │
│ 分配 → dma_buf_export() │
▼ │
┌───────────────────────────────────────────────────────────────┴───────────────┐
│ DMA-BUF CORE (drivers/dma-buf/dma-buf.c) │
│ │
│ struct dma_buf (共享缓冲对象, 由 anon file 承载, 引用计数) │
│ ├ ops : dma_buf_ops (由 Exporter 实现) │
│ ├ attachments : list<dma_buf_attachment> (每个 Importer 一个) │
│ ├ resv : dma_resv (同步对象: 独占/共享 fence) │
│ └ poll/cb_excl/cb_shared (用户态 poll 支持) │
│ │
│ 同步引擎: dma-fence.c (dma_fence: 时间线+seqno 的完成信号) │
│ dma-fence-array.c / dma-fence-chain.c (复合 fence) │
│ dma-resv.c (dma_resv: 用 ww_mutex + seqcount 管理 fences) │
│ sync_file.c / sw_sync.c (fence ↔ sync_file fd, 用户态时间线) │
│ ioctl/mmap/poll/统计: dma-buf.c / dma-buf-sysfs-stats.c │
└───────────▲───────────────────────────────────────────────┬──────────────────┘
│ Provider API (Exporter 侧) │ Consumer API (Importer 侧)
│ dma_buf_export() + struct dma_buf_ops │ dma_buf_attach/map/begin_cpu_access
▼ ▼
┌───────────────────────────────┐ ┌───────────────────────────────────┐
│ Exporter (缓冲提供者) │ │ Importer (缓冲使用者/设备) │
│ DRM GPU/VPU/VOP/KMS、ION、 │ │ DRM 显示控制器、V4L2、视频编解码、 │
│ v4l2、cameras、rk 各类驱动 │ │ NPU、 cameras、DMA 控制器 │
│ 实现 map_dma_buf/unmap_dma_buf │ │ dma_buf_attach → sg_table → 配置 │
│ /release/vmap/mmap/... │ │ 设备 DMA 地址 │
└───────────────────────────────┘ └───────────────────────────────────┘
2.2 关键源文件
| 文件 | 功能 |
|---|---|
drivers/dma-buf/dma-buf.c |
核心 :dma_buf_export/fd/get/put、attach/detach、map/unmap、begin/end_cpu_access、mmap、vmap/vunmap、ioctl、poll |
drivers/dma-buf/dma-fence.c |
同步原语 :dma_fence_init/get/put/signal/wait/add_callback/enable_sw_signaling |
drivers/dma-buf/dma-fence-array.c |
dma_fence_array:多 fence 聚合成一个 |
drivers/dma-buf/dma-fence-chain.c |
dma_fence_chain:时间线 fence 链 |
drivers/dma-buf/dma-resv.c |
预定对象 :dma_resv_init/fini、add/copy/get fences、test_signaled、wait_timeout |
drivers/dma-buf/dma-heap.c |
dma-heap 框架 :dma_heap_add/find/put、dma_heap_buffer_alloc、字符设备 |
drivers/dma-buf/heaps/system_heap.c |
系统内存堆 |
drivers/dma-buf/heaps/cma_heap.c / rk_cma_heap.c |
CMA 连续内存堆(标准 / Rockchip 版) |
drivers/dma-buf/heaps/rk_system_heap.c |
Rockchip 系统内存堆 |
drivers/dma-buf/heaps/sram_heap.c |
SRAM 堆 |
drivers/dma-buf/heaps/deferred-free-helper.c |
延迟释放辅助 |
drivers/dma-buf/sync_file.c |
fence ↔ sync_file fd |
drivers/dma-buf/sw_sync.c |
软件时间线 |
drivers/dma-buf/udmabuf.c |
memfd → dma-buf |
drivers/dma-buf/dma-buf-sysfs-stats.c |
sysfs 统计 |
drivers/dma-buf/dma-buf-cache.c |
Rockchip:attach/map 结果缓存 |
关键头文件:
| 文件 | 内容 |
|---|---|
include/linux/dma-buf.h |
dma_buf、dma_buf_attachment、dma_buf_ops、dma_buf_export_info |
include/linux/dma-fence.h |
dma_fence、dma_fence_ops、dma_fence_cb |
include/linux/dma-resv.h |
dma_resv、dma_resv_list、dma_resv_iter |
include/linux/dma-heap.h |
dma_heap_ops、dma_heap_export_info |
include/uapi/linux/dma-buf.h / dma-heap.h |
用户态 ioctl |
2.3 初始化顺序与依赖
text
DMA-HEAP 初始化
│
├─ dma_heap_init() 创建 /dev/dma_heap/ 类
├─ system_heap_create() / cma_heap_create() / rk_cma_heap_create()
│ └─ dma_heap_add(&exp_info)
│ └─ 为每个 heap 创建字符设备
DMA-BUF 使用
│
├─ 用户态 open("/dev/dma_heap/cma")
├─ ioctl(DMA_HEAP_IOCTL_ALLOC)
│ └─ dma_heap_ops->allocate() → dma_buf_export() → fd
│
├─ Exporter 完成填充
│ └─ dma_resv_add_excl_fence() → dma_fence_signal()
│
├─ fd 通过 SCM_RIGHTS 传
│
├─ Importer: dma_buf_get(fd) → dma_buf_attach() → dma_buf_map_attachment()
│
├─ 同步: dma_resv_wait_timeout_rcu()
│
├─ CPU 访问: dma_buf_begin_cpu_access() / end_cpu_access()
│
└─ 释放: dma_buf_unmap_attachment() → dma_buf_detach() → dma_buf_put()
3. Consumer API:Importer 如何使用 DMA-BUF
3.1 典型流程
text
Importer 驱动
│ dmabuf = dma_buf_get(fd) → 由 fd 拿句柄
│ attach = dma_buf_attach(dmabuf, dev) → 建立关系
│ sg = dma_buf_map_attachment(attach, DMA_TO_DEVICE) → 建立 DMA 映射
│ ... 用 sg_table 配置设备 ...
│ dma_resv_wait_timeout_rcu(...) → 等待 fence
│ dma_buf_unmap_attachment(attach, sg, dir) → 解除映射
│ dma_buf_detach(dmabuf, attach) → 解除关系
│ dma_buf_put(dmabuf) → 释放引用
▼
Importer 只持有 dma_buf、attachment、sg_table。
3.2 核心 API
c
/* 引用管理 */
struct dma_buf *dma_buf_get(int fd);
void dma_buf_put(struct dma_buf *dmabuf);
int dma_buf_fd(struct dma_buf *dmabuf, int flags);
static inline void get_dma_buf(struct dma_buf *dmabuf);
int is_dma_buf_file(struct file *file);
int get_each_dmabuf(int (*callback)(const struct dma_buf *, void *), void *private);
/* 建立关系 */
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, struct device *dev);
struct dma_buf_attachment *
dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
const struct dma_buf_attach_ops *importer_ops,
void *importer_priv);
void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach);
/* 固定 */
int dma_buf_pin(struct dma_buf_attachment *attach);
void dma_buf_unpin(struct dma_buf_attachment *attach);
/* 建立映射 */
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction);
void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
struct sg_table *table, enum dma_data_direction direction);
void dma_buf_move_notify(struct dma_buf *dma_buf);
/* CPU 访问 */
int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir);
int dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction dir,
unsigned int offset, unsigned int len);
int dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir);
int dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction dir,
unsigned int offset, unsigned int len);
/* mmap / vmap */
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, unsigned long vma_offset);
void *dma_buf_vmap(struct dma_buf *dmabuf);
void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr);
/* 属性 */
long dma_buf_set_name(struct dma_buf *dmabuf, const char *name);
int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags);
int dma_buf_get_uuid(struct dma_buf *dmabuf, uuid_t *uuid);
3.3 dma-fence API
c
/* 引用管理 */
static inline struct dma_fence *dma_fence_get(struct dma_fence *fence);
static inline void dma_fence_put(struct dma_fence *fence);
/* 等待 */
signed long dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout);
static inline signed long dma_fence_wait(struct dma_fence *fence, bool intr);
/* 回调 */
int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
dma_fence_func_t func);
bool dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb);
/* 查询 */
static inline bool dma_fence_is_signaled(struct dma_fence *fence);
int dma_fence_get_status(struct dma_fence *fence);
static inline bool dma_fence_is_later(struct dma_fence *f1, struct dma_fence *f2);
/* 标记完成(Provider 用) */
int dma_fence_signal(struct dma_fence *fence);
int dma_fence_signal_locked(struct dma_fence *fence);
int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp);
int dma_fence_signal_timestamp_locked(struct dma_fence *fence, ktime_t timestamp);
void dma_fence_enable_sw_signaling(struct dma_fence *fence);
u64 dma_fence_context_alloc(unsigned num);
static inline void dma_fence_set_error(struct dma_fence *fence, int error);
struct dma_fence *dma_fence_get_stub(void);
3.4 dma-resv API
c
/* 加锁 */
static inline int dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx);
static inline int dma_resv_lock_interruptible(struct dma_resv *obj, struct ww_acquire_ctx *ctx);
static inline void dma_resv_unlock(struct dma_resv *obj);
/* 添加 fence */
void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);
void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);
int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num);
/* 获取 */
int dma_resv_get_fences_rcu(struct dma_resv *obj, struct dma_fence **pfence_excl,
unsigned *pshared_count, struct dma_fence ***pshared);
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);
/* 查询/等待 */
bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all);
long dma_resv_wait_timeout_rcu(struct dma_resv *obj, bool wait_all, bool intr,
unsigned long timeout);
3.5 dma-heap API(内核侧)
c
struct dma_heap *dma_heap_find(const char *name);
void dma_heap_put(struct dma_heap *heap);
struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
unsigned int fd_flags, unsigned int heap_flags);
int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
unsigned int fd_flags, unsigned int heap_flags);
void dma_heap_buffer_free(struct dma_buf *dmabuf);
3.6 sync_file / sw_sync API
c
struct sync_file *sync_file_create(struct dma_fence *fence);
struct dma_fence *sync_file_get_fence(int fd);
struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
int sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
3.7 典型使用示例(Importer)
c
static int my_importer_use_dmabuf(int fd)
{
struct dma_buf *dmabuf;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
long ret;
dmabuf = dma_buf_get(fd);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
attach = dma_buf_attach(dmabuf, my_dev);
if (IS_ERR(attach)) {
ret = PTR_ERR(attach);
goto err_put;
}
sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto err_detach;
}
/* 等待写者 fence 完成 */
ret = dma_resv_wait_timeout_rcu(dmabuf->resv, true, true, msecs_to_jiffies(1000));
if (ret <= 0) {
ret = -ETIMEDOUT;
goto err_unmap;
}
/* 用 sgt 配置设备 ... */
dma_buf_unmap_attachment(attach, sgt, DMA_TO_DEVICE);
dma_buf_detach(dmabuf, attach);
dma_buf_put(dmabuf);
return 0;
err_unmap:
dma_buf_unmap_attachment(attach, sgt, DMA_TO_DEVICE);
err_detach:
dma_buf_detach(dmabuf, attach);
err_put:
dma_buf_put(dmabuf);
return ret;
}
4. Core 核心层:dma-buf 的生命周期与同步
4.1 Core 的职责
- 维护
dma_buf生命周期:dma_buf_export()/dma_buf_get()/dma_buf_put()。 - 管理 fd:
dma_buf_fd()安装 anon file。 - 管理 attachments:
dma_buf_attach()/detach()。 - 管理映射:
dma_buf_map_attachment()/unmap_attachment()。 - 管理 CPU 访问:
begin_cpu_access/end_cpu_access。 - 管理 vmap/mmap。
- 提供 ioctl:
SYNC/SET_NAME/GET_FLAGS/GET_UUID。 - 提供 poll。
- 提供 sysfs 统计。
4.2 生命周期
text
dma_buf_export(exp_info)
│ 分配 struct dma_buf
│ 创建 anon file (dma_buf->file)
│ 校验 ops (map_dma_buf/unmap_dma_buf/release 必须存在)
│ 若 exp_info->resv 为 NULL,分配内嵌 resv
▼
dma_buf 可用
│ dma_buf_fd() 安装 fd
│ dma_buf_get(fd) 增加引用
▼
attach / map / 使用
│ dma_buf_put() 减少引用
▼
引用归零 → fput() → dma_buf_release() → ops->release()
4.3 attach / map 流程
text
Importer: dma_buf_attach(dmabuf, dev)
│
├─ 分配 dma_buf_attachment
├─ 若 dmabuf->ops->attach 存在,调用
├─ 加入 dmabuf->attachments
└─ 返回 attachment
Importer: dma_buf_map_attachment(attach, direction)
│
├─ 若 cache_sgt_mapping && attach->sgt 已存在,直接返回
├─ 调用 dmabuf->ops->map_dma_buf(attach, direction)
│ └─ Exporter 返回 sg_table
├─ 若 cache_sgt_mapping,缓存 attach->sgt
└─ 返回 sg_table
4.4 同步:dma_resv
dma_resv 用 ww_mutex + seqcount 管理 fence:
text
写者提交:
dma_resv_lock(resv, &ctx)
dma_resv_add_excl_fence(resv, write_fence)
dma_resv_unlock(resv)
读者提交:
dma_resv_lock(resv, &ctx)
dma_resv_add_shared_fence(resv, read_fence)
dma_resv_unlock(resv)
等待:
dma_resv_wait_timeout_rcu(resv, wait_all=true, intr=true, timeout)
├─ RCU 读 fence_excl 与 shared[]
└─ 逐个 dma_fence_wait_timeout
关键设计:
ww_mutex保证多锁顺序,防死锁;seqcount保证 RCU 读侧一致性;fence_excl与fence分离,写者与读者分别管理。
4.5 dma_fence 的 signaling 临界区
dma_fence 有一个重要的防死锁机制:
dma_fence_begin_signalling():进入 signaling 临界区;dma_fence_end_signalling():退出;- 在临界区内,fence 不能被非法 signal,防止死锁。
4.6 用户态 ioctl
c
DMA_BUF_IOCTL_SYNC /* CPU 访问前后同步 cache */
DMA_BUF_IOCTL_SET_NAME /* 设置名字 */
DMA_BUF_IOCTL_GET_FLAGS /* 获取 flags */
DMA_BUF_IOCTL_GET_UUID /* 获取 UUID */
DMA_HEAP_IOCTL_ALLOC /* 从 heap 分配 dma-buf */
4.7 poll 支持
dma_buf 支持用户态 poll():
cb_excl:独占 fence 回调;cb_shared:共享 fence 回调;- 当 fence 完成时唤醒 poll 等待者。
5. Provider API:Exporter / Heap / Fence 如何注册
5.1 Exporter 的核心类
| 类 | 作用 |
|---|---|
dma_buf_ops |
内存分配/映射/释放回调表 |
dma_buf_export_info |
导出信息 |
dma_buf_attach_ops |
动态映射 Importer 回调 |
5.2 Exporter 注册流程
c
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
#define DEFINE_DMA_BUF_EXPORT_INFO(name)
dma_buf_ops 必须实现:
map_dma_buf:建立 DMA 映射,返回 sg_table;unmap_dma_buf:解除映射;release:释放底层内存。
dma_buf_ops 可选实现:
attach/detach:建立/解除关系;pin/unpin:固定不可移动;begin_cpu_access/end_cpu_access:CPU 访问一致性;mmap:用户态 mmap;vmap/vunmap:内核态 vmap;get_uuid/get_flags。
5.3 dma-fence Provider
c
void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
spinlock_t *lock, u64 context, u64 seqno);
void dma_fence_release(struct kref *kref);
void dma_fence_free(struct dma_fence *fence);
bool dma_fence_begin_signalling(void);
void dma_fence_end_signalling(bool cookie);
dma_fence_ops 必须实现:
get_driver_name;get_timeline_name;release。
dma_fence_ops 可选实现:
enable_signaling:使能软/硬 signaling;signaled:快速查询;wait:自定义等待;fence_value_str/timeline_value_str:debugfs。
5.4 复合 fence
c
struct dma_fence_array *dma_fence_array_create(int num_fences, struct dma_fence **fences,
u64 context, unsigned seqno, bool signal_on_any);
struct dma_fence_chain *dma_fence_chain_alloc(void);
void dma_fence_chain_free(struct dma_fence_chain *chain);
void dma_fence_chain_init(struct dma_fence_chain *chain, struct dma_fence *prev,
struct dma_fence *fence, u64 seqno);
struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence);
int dma_fence_chain_find_seqno(struct dma_fence **pfence, u64 seqno);
5.5 dma-resv Provider
c
void dma_resv_init(struct dma_resv *obj);
void dma_resv_fini(struct dma_resv *obj);
5.6 dma-heap Provider
c
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
dma_heap_ops 必须实现:
allocate:分配 dma_buf。
dma_heap_ops 可选实现:
get_pool_size:查询池大小;get_phys:获取物理地址。
5.7 Rockchip 扩展
c
#ifdef CONFIG_DMABUF_CACHE
struct dma_buf_attachment *dma_buf_cache_attach(struct dma_buf *dmabuf, struct device *dev);
void dma_buf_cache_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach);
struct sg_table *dma_buf_cache_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction);
void dma_buf_cache_unmap_attachment(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
enum dma_data_direction direction);
#endif
#ifdef CONFIG_DMABUF_HEAPS_ROCKCHIP
struct rk_dma_heap *rk_dma_heap_find(const char *name);
struct dma_buf *rk_dma_heap_buffer_alloc(struct rk_dma_heap *heap, size_t len,
unsigned int fd_flags, unsigned int heap_flags,
const char *name);
int rk_dma_heap_bufferfd_alloc(struct rk_dma_heap *heap, size_t len,
unsigned int fd_flags, unsigned int heap_flags, const char *name);
struct page *rk_dma_heap_alloc_contig_pages(struct rk_dma_heap *heap, size_t len, const char *name);
void rk_dma_heap_free_contig_pages(struct rk_dma_heap *heap, struct page *pages,
size_t len, const char *name);
int rk_dma_heap_cma_setup(void);
int rk_dma_heap_set_dev(struct device *heap_dev);
#endif
6. UML 类图:从 Exporter 到 Importer
说明:Mermaid 类图中的
note描述类的作用;类图后的表格补充关键成员职责。
6.1 核心对象类图
#mermaid-svg-w8yBXdniwWYuUF7r{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-w8yBXdniwWYuUF7r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-w8yBXdniwWYuUF7r .error-icon{fill:#552222;}#mermaid-svg-w8yBXdniwWYuUF7r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-w8yBXdniwWYuUF7r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-w8yBXdniwWYuUF7r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-w8yBXdniwWYuUF7r .marker.cross{stroke:#333333;}#mermaid-svg-w8yBXdniwWYuUF7r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-w8yBXdniwWYuUF7r p{margin:0;}#mermaid-svg-w8yBXdniwWYuUF7r g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-w8yBXdniwWYuUF7r g.classGroup text .title{font-weight:bolder;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster-label text{fill:#333;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster-label span{color:#333;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster-label span p{background-color:transparent;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster text{fill:#333;}#mermaid-svg-w8yBXdniwWYuUF7r .cluster span{color:#333;}#mermaid-svg-w8yBXdniwWYuUF7r .nodeLabel,#mermaid-svg-w8yBXdniwWYuUF7r .edgeLabel{color:#131300;}#mermaid-svg-w8yBXdniwWYuUF7r .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-w8yBXdniwWYuUF7r .label text{fill:#131300;}#mermaid-svg-w8yBXdniwWYuUF7r .labelBkg{background:#ECECFF;}#mermaid-svg-w8yBXdniwWYuUF7r .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-w8yBXdniwWYuUF7r .classTitle{font-weight:bolder;}#mermaid-svg-w8yBXdniwWYuUF7r .node rect,#mermaid-svg-w8yBXdniwWYuUF7r .node circle,#mermaid-svg-w8yBXdniwWYuUF7r .node ellipse,#mermaid-svg-w8yBXdniwWYuUF7r .node polygon,#mermaid-svg-w8yBXdniwWYuUF7r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-w8yBXdniwWYuUF7r .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r g.clickable{cursor:pointer;}#mermaid-svg-w8yBXdniwWYuUF7r g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-w8yBXdniwWYuUF7r g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-w8yBXdniwWYuUF7r .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-w8yBXdniwWYuUF7r .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-w8yBXdniwWYuUF7r .dashed-line{stroke-dasharray:3;}#mermaid-svg-w8yBXdniwWYuUF7r .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-w8yBXdniwWYuUF7r #compositionStart,#mermaid-svg-w8yBXdniwWYuUF7r .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #compositionEnd,#mermaid-svg-w8yBXdniwWYuUF7r .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #dependencyStart,#mermaid-svg-w8yBXdniwWYuUF7r .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #dependencyStart,#mermaid-svg-w8yBXdniwWYuUF7r .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #extensionStart,#mermaid-svg-w8yBXdniwWYuUF7r .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #extensionEnd,#mermaid-svg-w8yBXdniwWYuUF7r .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #aggregationStart,#mermaid-svg-w8yBXdniwWYuUF7r .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #aggregationEnd,#mermaid-svg-w8yBXdniwWYuUF7r .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #lollipopStart,#mermaid-svg-w8yBXdniwWYuUF7r .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r #lollipopEnd,#mermaid-svg-w8yBXdniwWYuUF7r .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w8yBXdniwWYuUF7r .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-w8yBXdniwWYuUF7r .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-w8yBXdniwWYuUF7r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-w8yBXdniwWYuUF7r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-w8yBXdniwWYuUF7r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ops
attachments
dmabuf
importer_ops
ops
resv
1
*
DmaBuf
+size : size_t
+file : file
+attachments : list_head
+ops : DmaBufOps
+lock : mutex
+vmapping_counter : unsigned
+vmap_ptr : void
+exp_name : const char
+name : const char
+owner : module
+list_node : list_head
+priv : void
+resv : DmaResv
+poll : wait_queue_head_t
+cb_excl : DmaBufPollCbT
+cb_shared : DmaBufPollCbT
DmaBufOps
+cache_sgt_mapping : bool
+attach()
+detach()
+pin()
+unpin()
+map_dma_buf()
+unmap_dma_buf()
+release()
+begin_cpu_access()
+begin_cpu_access_partial()
+end_cpu_access()
+end_cpu_access_partial()
+mmap()
+vmap()
+vunmap()
+get_uuid()
+get_flags()
DmaBufAttachment
+dmabuf : DmaBuf
+dev : device
+node : list_head
+sgt : sg_table
+dir : enum dma_data_direction
+peer2peer : bool
+importer_ops : DmaBufAttachOps
+importer_priv : void
+priv : void
+dma_map_attrs : unsigned long
DmaBufAttachOps
+allow_peer2peer : bool
+move_notify()
DmaBufExportInfo
+exp_name : const char
+owner : module
+ops : DmaBufOps
+size : size_t
+flags : int
+resv : DmaResv
+priv : void
DmaResv
共享缓冲对象:由 anon file 承载,引用计数管理。
Exporter 回调表:内存/映射/释放。
设备↔缓冲关系:每个 Importer 一个。
动态映射 Importer 回调。
导出信息:name/owner/ops/size/flags/resv/priv。
| 类 | 作用 | 关键成员说明 |
|---|---|---|
DmaBuf |
共享缓冲 | file anon file;attachments 所有 Importer;ops Exporter 回调;resv 同步对象;poll 用户态 poll |
DmaBufOps |
Exporter 回调 | map_dma_buf/unmap_dma_buf/release 必须;cache_sgt_mapping 缓存映射 |
DmaBufAttachment |
设备↔缓冲 | dev 使用设备;sgt 缓存映射;dir 方向;peer2peer P2P 支持 |
DmaBufAttachOps |
动态 Importer | move_notify 缓冲移动通知 |
DmaBufExportInfo |
导出信息 | resv 可 NULL,Core 分配默认 |
6.2 同步对象类图
#mermaid-svg-OK479GV6kIl0OmQw{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-OK479GV6kIl0OmQw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OK479GV6kIl0OmQw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OK479GV6kIl0OmQw .error-icon{fill:#552222;}#mermaid-svg-OK479GV6kIl0OmQw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OK479GV6kIl0OmQw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OK479GV6kIl0OmQw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OK479GV6kIl0OmQw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OK479GV6kIl0OmQw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OK479GV6kIl0OmQw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OK479GV6kIl0OmQw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OK479GV6kIl0OmQw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OK479GV6kIl0OmQw .marker.cross{stroke:#333333;}#mermaid-svg-OK479GV6kIl0OmQw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OK479GV6kIl0OmQw p{margin:0;}#mermaid-svg-OK479GV6kIl0OmQw g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-OK479GV6kIl0OmQw g.classGroup text .title{font-weight:bolder;}#mermaid-svg-OK479GV6kIl0OmQw .cluster-label text{fill:#333;}#mermaid-svg-OK479GV6kIl0OmQw .cluster-label span{color:#333;}#mermaid-svg-OK479GV6kIl0OmQw .cluster-label span p{background-color:transparent;}#mermaid-svg-OK479GV6kIl0OmQw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OK479GV6kIl0OmQw .cluster text{fill:#333;}#mermaid-svg-OK479GV6kIl0OmQw .cluster span{color:#333;}#mermaid-svg-OK479GV6kIl0OmQw .nodeLabel,#mermaid-svg-OK479GV6kIl0OmQw .edgeLabel{color:#131300;}#mermaid-svg-OK479GV6kIl0OmQw .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-OK479GV6kIl0OmQw .label text{fill:#131300;}#mermaid-svg-OK479GV6kIl0OmQw .labelBkg{background:#ECECFF;}#mermaid-svg-OK479GV6kIl0OmQw .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-OK479GV6kIl0OmQw .classTitle{font-weight:bolder;}#mermaid-svg-OK479GV6kIl0OmQw .node rect,#mermaid-svg-OK479GV6kIl0OmQw .node circle,#mermaid-svg-OK479GV6kIl0OmQw .node ellipse,#mermaid-svg-OK479GV6kIl0OmQw .node polygon,#mermaid-svg-OK479GV6kIl0OmQw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OK479GV6kIl0OmQw .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw g.clickable{cursor:pointer;}#mermaid-svg-OK479GV6kIl0OmQw g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-OK479GV6kIl0OmQw g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-OK479GV6kIl0OmQw .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-OK479GV6kIl0OmQw .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-OK479GV6kIl0OmQw .dashed-line{stroke-dasharray:3;}#mermaid-svg-OK479GV6kIl0OmQw .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-OK479GV6kIl0OmQw #compositionStart,#mermaid-svg-OK479GV6kIl0OmQw .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #compositionEnd,#mermaid-svg-OK479GV6kIl0OmQw .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #dependencyStart,#mermaid-svg-OK479GV6kIl0OmQw .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #dependencyStart,#mermaid-svg-OK479GV6kIl0OmQw .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #extensionStart,#mermaid-svg-OK479GV6kIl0OmQw .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #extensionEnd,#mermaid-svg-OK479GV6kIl0OmQw .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #aggregationStart,#mermaid-svg-OK479GV6kIl0OmQw .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #aggregationEnd,#mermaid-svg-OK479GV6kIl0OmQw .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #lollipopStart,#mermaid-svg-OK479GV6kIl0OmQw .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw #lollipopEnd,#mermaid-svg-OK479GV6kIl0OmQw .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OK479GV6kIl0OmQw .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-OK479GV6kIl0OmQw .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OK479GV6kIl0OmQw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OK479GV6kIl0OmQw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OK479GV6kIl0OmQw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ops
cb_list
fence_excl
fence
shared\[\]
base
base
DmaFence
+lock : spinlock_t
+ops : DmaFenceOps
+cb_list : list_head
+context : u64
+seqno : u64
+flags : unsigned long
+refcount : kref
+error : int
DmaFenceOps
+use_64bit_seqno : bool
+get_driver_name()
+get_timeline_name()
+enable_signaling()
+signaled()
+wait()
+release()
+fence_value_str()
+timeline_value_str()
DmaFenceCb
+node : list_head
+func : dma_fence_func_t
DmaResv
+lock : ww_mutex
+seq : seqcount_ww_mutex_t
+fence_excl : DmaFence
+fence : DmaResvList
DmaResvList
+rcu : rcu_head
+shared_count : u32
+shared_max : u32
+shared : DmaFence*\[\]
DmaFenceArray
+base : DmaFence
+lock : spinlock_t
+num_fences : unsigned
+num_pending : atomic_t
+fences : DmaFence*
DmaFenceChain
+base : DmaFence
+lock : spinlock_t
+prev : DmaFence
+prev_seqno : u64
+fence : DmaFence
同步原语:时间线 + seqno 的完成信号。
Fence 回调表:signaling/wait/release。
完成回调:node + func。
预定对象:ww_mutex + seqcount + 独占/共享 fence。
共享 fence 表:RCU 保护。
复合 fence:多 fence 聚合。
链式 fence:时间线顺序依赖。
| 类 | 作用 | 关键成员说明 |
|---|---|---|
DmaFence |
同步原语 | context 时间线;seqno 序号;cb_list 回调;error 错误 |
DmaFenceOps |
Fence 回调 | enable_signaling/signaled/wait/release |
DmaFenceCb |
完成回调 | func 回调函数 |
DmaResv |
预定对象 | fence_excl 写者;fence 读者表;lock ww_mutex;seq seqcount |
DmaResvList |
共享表 | shared[] RCU 数组 |
DmaFenceArray |
复合 fence | num_pending 计数;signal_on_any |
DmaFenceChain |
链式 fence | prev 前驱;fence 当前 |
勘误:
dma_fence的cb_list/timestamp/rcu是 union,不是同时存在。
6.3 Heap 与用户态类图
#mermaid-svg-yHHiXbHWQhRJOrrX{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-yHHiXbHWQhRJOrrX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yHHiXbHWQhRJOrrX .error-icon{fill:#552222;}#mermaid-svg-yHHiXbHWQhRJOrrX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yHHiXbHWQhRJOrrX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yHHiXbHWQhRJOrrX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yHHiXbHWQhRJOrrX .marker.cross{stroke:#333333;}#mermaid-svg-yHHiXbHWQhRJOrrX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yHHiXbHWQhRJOrrX p{margin:0;}#mermaid-svg-yHHiXbHWQhRJOrrX g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-yHHiXbHWQhRJOrrX g.classGroup text .title{font-weight:bolder;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster-label text{fill:#333;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster-label span{color:#333;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster-label span p{background-color:transparent;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster text{fill:#333;}#mermaid-svg-yHHiXbHWQhRJOrrX .cluster span{color:#333;}#mermaid-svg-yHHiXbHWQhRJOrrX .nodeLabel,#mermaid-svg-yHHiXbHWQhRJOrrX .edgeLabel{color:#131300;}#mermaid-svg-yHHiXbHWQhRJOrrX .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-yHHiXbHWQhRJOrrX .label text{fill:#131300;}#mermaid-svg-yHHiXbHWQhRJOrrX .labelBkg{background:#ECECFF;}#mermaid-svg-yHHiXbHWQhRJOrrX .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-yHHiXbHWQhRJOrrX .classTitle{font-weight:bolder;}#mermaid-svg-yHHiXbHWQhRJOrrX .node rect,#mermaid-svg-yHHiXbHWQhRJOrrX .node circle,#mermaid-svg-yHHiXbHWQhRJOrrX .node ellipse,#mermaid-svg-yHHiXbHWQhRJOrrX .node polygon,#mermaid-svg-yHHiXbHWQhRJOrrX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yHHiXbHWQhRJOrrX .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX g.clickable{cursor:pointer;}#mermaid-svg-yHHiXbHWQhRJOrrX g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-yHHiXbHWQhRJOrrX g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-yHHiXbHWQhRJOrrX .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-yHHiXbHWQhRJOrrX .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-yHHiXbHWQhRJOrrX .dashed-line{stroke-dasharray:3;}#mermaid-svg-yHHiXbHWQhRJOrrX .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-yHHiXbHWQhRJOrrX #compositionStart,#mermaid-svg-yHHiXbHWQhRJOrrX .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #compositionEnd,#mermaid-svg-yHHiXbHWQhRJOrrX .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #dependencyStart,#mermaid-svg-yHHiXbHWQhRJOrrX .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #dependencyStart,#mermaid-svg-yHHiXbHWQhRJOrrX .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #extensionStart,#mermaid-svg-yHHiXbHWQhRJOrrX .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #extensionEnd,#mermaid-svg-yHHiXbHWQhRJOrrX .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #aggregationStart,#mermaid-svg-yHHiXbHWQhRJOrrX .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #aggregationEnd,#mermaid-svg-yHHiXbHWQhRJOrrX .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #lollipopStart,#mermaid-svg-yHHiXbHWQhRJOrrX .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX #lollipopEnd,#mermaid-svg-yHHiXbHWQhRJOrrX .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yHHiXbHWQhRJOrrX .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-yHHiXbHWQhRJOrrX .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yHHiXbHWQhRJOrrX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yHHiXbHWQhRJOrrX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yHHiXbHWQhRJOrrX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ops
ops
fence
生成
DmaHeap
+name : const char
+ops : DmaHeapOps
+priv : void
+dev : device
+refcount : atomic_t
DmaHeapOps
+allocate()
+get_pool_size()
+get_phys()
DmaHeapExportInfo
+name : const char
+ops : DmaHeapOps
+priv : void
SyncFile
+file : file
+fence : DmaFence
+wq : wait_queue_head
+cb : DmaFenceCb
+flags : unsigned long
SwSyncTimeline
+obj : sync_timeline
+name : const char
DmaFence
堆运行时对象:/dev/dma_heap/。
堆分配回调:allocate 必须。
堆导出信息。
fence ↔ fd 桥接。
软件时间线:测试/合成用。
| 类 | 作用 | 关键成员说明 |
|---|---|---|
DmaHeap |
堆对象 | name 名;ops 回调;dev 字符设备 |
DmaHeapOps |
堆回调 | allocate 分配 dma_buf |
DmaHeapExportInfo |
导出信息 | name/ops/priv |
SyncFile |
fence fd | fence 目标;wq 等待队列 |
SwSyncTimeline |
软件时间线 | 生成 fence |
6.4 Rockchip 扩展类图
#mermaid-svg-kfku9Ta2ixNS4bCE{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-kfku9Ta2ixNS4bCE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kfku9Ta2ixNS4bCE .error-icon{fill:#552222;}#mermaid-svg-kfku9Ta2ixNS4bCE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kfku9Ta2ixNS4bCE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kfku9Ta2ixNS4bCE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kfku9Ta2ixNS4bCE .marker.cross{stroke:#333333;}#mermaid-svg-kfku9Ta2ixNS4bCE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kfku9Ta2ixNS4bCE p{margin:0;}#mermaid-svg-kfku9Ta2ixNS4bCE g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-kfku9Ta2ixNS4bCE g.classGroup text .title{font-weight:bolder;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster-label text{fill:#333;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster-label span{color:#333;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster-label span p{background-color:transparent;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster text{fill:#333;}#mermaid-svg-kfku9Ta2ixNS4bCE .cluster span{color:#333;}#mermaid-svg-kfku9Ta2ixNS4bCE .nodeLabel,#mermaid-svg-kfku9Ta2ixNS4bCE .edgeLabel{color:#131300;}#mermaid-svg-kfku9Ta2ixNS4bCE .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-kfku9Ta2ixNS4bCE .label text{fill:#131300;}#mermaid-svg-kfku9Ta2ixNS4bCE .labelBkg{background:#ECECFF;}#mermaid-svg-kfku9Ta2ixNS4bCE .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-kfku9Ta2ixNS4bCE .classTitle{font-weight:bolder;}#mermaid-svg-kfku9Ta2ixNS4bCE .node rect,#mermaid-svg-kfku9Ta2ixNS4bCE .node circle,#mermaid-svg-kfku9Ta2ixNS4bCE .node ellipse,#mermaid-svg-kfku9Ta2ixNS4bCE .node polygon,#mermaid-svg-kfku9Ta2ixNS4bCE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kfku9Ta2ixNS4bCE .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE g.clickable{cursor:pointer;}#mermaid-svg-kfku9Ta2ixNS4bCE g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-kfku9Ta2ixNS4bCE g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-kfku9Ta2ixNS4bCE .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-kfku9Ta2ixNS4bCE .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-kfku9Ta2ixNS4bCE .dashed-line{stroke-dasharray:3;}#mermaid-svg-kfku9Ta2ixNS4bCE .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-kfku9Ta2ixNS4bCE #compositionStart,#mermaid-svg-kfku9Ta2ixNS4bCE .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #compositionEnd,#mermaid-svg-kfku9Ta2ixNS4bCE .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #dependencyStart,#mermaid-svg-kfku9Ta2ixNS4bCE .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #dependencyStart,#mermaid-svg-kfku9Ta2ixNS4bCE .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #extensionStart,#mermaid-svg-kfku9Ta2ixNS4bCE .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #extensionEnd,#mermaid-svg-kfku9Ta2ixNS4bCE .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #aggregationStart,#mermaid-svg-kfku9Ta2ixNS4bCE .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #aggregationEnd,#mermaid-svg-kfku9Ta2ixNS4bCE .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #lollipopStart,#mermaid-svg-kfku9Ta2ixNS4bCE .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE #lollipopEnd,#mermaid-svg-kfku9Ta2ixNS4bCE .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-kfku9Ta2ixNS4bCE .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-kfku9Ta2ixNS4bCE .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kfku9Ta2ixNS4bCE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kfku9Ta2ixNS4bCE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kfku9Ta2ixNS4bCE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} heap
ops
<<extension>>
DmaBufCache
+dma_buf_cache_attach()
+dma_buf_cache_detach()
+dma_buf_cache_map_attachment()
+dma_buf_cache_unmap_attachment()
RkDmaHeap
+name : const char
+heap : DmaHeap
RkDmaHeapOps
+rk_dma_heap_buffer_alloc()
+rk_dma_heap_alloc_contig_pages()
+rk_dma_heap_free_contig_pages()
DmaHeap
attach/map 结果缓存,宏覆盖核心 API。
Rockchip heap:命名分配、连续页。
7. 典型数据流:一次跨设备零拷贝共享
text
用户态: open("/dev/dma_heap/cma") → ioctl(DMA_HEAP_IOCTL_ALLOC, len)
└ dma_heap_ops->allocate() → dma_buf_export() → fd A
Exporter(内存分配者) 完成填充后: dma_fence_signal()
(通过 dma_resv_add_excl_fence 登记)
fd A 通过 SCM_RIGHTS 传给另一进程/驱动
Importer1: dma_buf_get(fdA)
→ dma_buf_attach(dev1)
→ dma_buf_map_attachment()
→ sg_table1
Importer2: dma_buf_attach(dev2)
→ dma_buf_map_attachment()
→ sg_table2
(同一物理内存!)
同步:
dma_resv_lock()
dma_resv_add_excl_fence(写者 fence)
dma_resv_unlock()
Importer 读前 dma_resv_test_signaled/wait_timeout 等写者 fence 完成
CPU 访问:
dma_buf_begin_cpu_access() / end_cpu_access()
(Exporter flush cache)
释放:
dma_buf_unmap_attachment()
→ dma_buf_detach()
→ dma_buf_put()
→ ops->release()
8. 逻辑漏洞与修正清单
| 原文档说法 | 问题 | 修正 |
|---|---|---|
dma_buf_get() 是内核侧增加引用 |
不准确 | dma_buf_get() 从 fd 拿引用;内核额外持有应用 get_dma_buf() |
dma_buf_put() 立即释放 |
不准确 | 引用计数归零才调用 ops->release() |
dma_buf_attach() 与 dma_buf_dynamic_attach() 等价 |
不准确 | 后者提供 importer_ops,支持动态映射 |
dma_buf_map_attachment() 每次调用都重新映射 |
不准确 | 若 cache_sgt_mapping,会复用缓存的 sgt |
dma_buf_attachment.sgt 是必需字段 |
不准确 | 仅当 cache_sgt_mapping 时缓存 |
dma_buf_pin() 与 dma_buf_map_attachment() 等价 |
概念混淆 | pin 表示缓冲不可移动;map 建立 DMA 映射 |
dma_buf_ops->attach 是必须实现 |
错误 | 可选;map_dma_buf/unmap_dma_buf/release 才是必须 |
dma_buf_ops->pin 是必须实现 |
错误 | 可选;未实现则为静态映射 |
dma_buf_begin_cpu_access 由 Core 负责 cache flush |
错误 | 由 Exporter 实现 |
dma_buf_mmap 返回的映射是 cache 一致的 |
错误 | 是 incoherent 的,用户态需 DMA_BUF_IOCTL_SYNC |
dma_fence_signal 可重复调用 |
正确 | 重复调用返回 -EINVAL |
dma_fence_signal 可在任意上下文调用 |
不准确 | 需注意 lock 与 signaling 临界区 |
dma_fence_add_callback 在 fence 已完成时返回 0 |
错误 | 返回 -ENOENT,且立即调用回调 |
dma_fence_wait 只能在进程上下文 |
正确 | 会睡眠 |
dma_fence_wait_timeout 返回剩余超时 |
正确 | 0 表示超时 |
dma_fence_is_later 跨 context 比较 |
错误 | 只对同一 context 有效 |
dma_fence_ops->release 是可选的 |
错误 | 必须实现 |
dma_fence_ops->enable_signaling 是可选的 |
正确 | 未实现则默认已 signaled |
dma_resv 只用 ww_mutex |
不完整 | 还有 seqcount 用于 RCU 读 |
dma_resv_add_excl_fence 可同时加多个 |
错误 | 独占 fence 只有一个,新加会替换 |
dma_resv_add_shared_fence 无上限 |
不准确 | 需先 dma_resv_reserve_shared |
dma_resv_wait_timeout_rcu 不需要锁 |
正确 | RCU 读不需要 ww_mutex |
dma_resv_lock 与 dma_resv_lock_interruptible 等价 |
不准确 | 后者可被信号打断 |
dma_heap_add 自动创建 fd |
不准确 | 只注册 heap;分配走 dma_heap_buffer_alloc |
dma_heap_find 不需要 put |
错误 | 必须 dma_heap_put |
sync_file_create 不增加 fence 引用 |
错误 | 会 dma_fence_get |
sync_file_get_fence 不增加引用 |
错误 | 返回的 fence 需要 dma_fence_put |
sw_sync_timeline_inc 可任意 inc |
正确 | 但需保证单调 |
dma_fence_array 默认 signal_on_any |
错误 | 默认全部完成才完成 |
dma_fence_chain 与 dma_fence_array 等价 |
错误 | chain 有时间线顺序语义 |
udmabuf 支持所有 memfd |
不准确 | 只支持 hugetlbfs/shmem 的特定配置 |
DMA_BUF_IOCTL_SYNC 可省略 |
错误 | CPU 访问前后必须调用 |
dma-buf-cache 是标准内核功能 |
错误 | 是 Rockchip 扩展 |
rk_cma_heap 是标准 CMA heap |
不准确 | Rockchip 增强版,支持命名分配 |
9. 调试与实操
9.1 sysfs / debugfs
/sys/kernel/dmabuf/:dma-buf 统计;/sys/kernel/debug/dma_buf/:debugfs 详情;/dev/dma_heap/:可用的 heap。
9.2 常用命令
bash
# 查看所有 heap
ls /dev/dma_heap/
# 查看 dma-buf 统计
cat /sys/kernel/dmabuf/buffers
# 查看单个 buffer
cat /sys/kernel/dmabuf/buffers/<inode>/info
# 使用 dma-buf 工具
dma_heap_alloc --heap=cma --size=4096
9.3 常见错误码
| 错误码 | 含义 | 处理 |
|---|---|---|
-ENOENT |
fd 不是 dma-buf | 检查 fd 来源 |
-EBADF |
fd 无效 | 检查 fd 是否关闭 |
-EINVAL |
参数非法 | 检查 size/flags |
-ENOMEM |
分配失败 | 检查 heap 容量 |
-ETIMEDOUT |
fence 等待超时 | 检查设备是否挂死 |
-EDEADLK |
dma_resv 死锁 | 重试 ww_mutex |
-EPERM |
权限不足 | 检查 /dev/dma_heap 权限 |
9.4 验证步骤
ls /dev/dma_heap/确认 heap 注册;cat /sys/kernel/dmabuf/buffers确认 buffer 统计;- 分配一个 buffer,确认 fd 有效;
dma_buf_get(fd)拿到句柄;dma_buf_attach+dma_buf_map_attachment确认 sg_table;- 用
dma_resv_wait_timeout_rcu验证 fence 同步; dma_buf_begin_cpu_access/end_cpu_access验证 cache 一致性。
10. 总结
DMA-BUF 子系统的本质是:
用 fd 即句柄 + Exporter/Importer 分离 + dma_fence/dma_resv 同步 三件套,把"跨设备共享、跨进程传递、零拷贝、DMA 映射、cache 一致性、生命周期"全部收口到
drivers/dma-buf/。
理解 DMA-BUF 的关键是抓住四条线:
- 句柄线 :
dma_buf_fd()→ fd →dma_buf_get()→dma_buf_put(); - 映射线 :
dma_buf_attach()→dma_buf_map_attachment()→sg_table→dma_buf_unmap_attachment(); - 同步线 :
dma_fence→dma_resv→add_excl/shared_fence→wait_timeout_rcu; - 分配线 :
dma_heap_add()→dma_heap_ops->allocate()→dma_buf_export()。
掌握这四条线,再看 dma-buf.c、dma-fence.c、dma-resv.c、dma-heap.c 和 Rockchip 的 rk_cma_heap.c / dma-buf-cache.c,就能把 DMA-BUF 子系统串起来。
附:关键源码位置速查
| 主题 | 位置 |
|---|---|
| 核心对象/ops | include/linux/dma-buf.h(dma_buf_ops:36、dma_buf:410、dma_buf_attachment:511、dma_buf_export_info:540) |
| 核心实现 | drivers/dma-buf/dma-buf.c(dma_buf_export:669、dma_buf_attach:939、dma_buf_map_attachment:1044、dma_buf_begin_cpu_access:1267、dma_buf_vmap:1423) |
| fence | include/linux/dma-fence.h(dma_fence:65、dma_fence_ops:125);drivers/dma-buf/dma-fence.c |
| resv | include/linux/dma-resv.h:70;drivers/dma-buf/dma-resv.c |
| heap | include/linux/dma-heap.h;drivers/dma-buf/dma-heap.c;heaps/{system,cma,rk_cma,sram}_heap.c |
| fence 复合 | drivers/dma-buf/dma-fence-array.c、dma-fence-chain.c |
| 用户态同步 | drivers/dma-buf/sync_file.c、sw_sync.c |
| Rockchip 扩展 | include/linux/dma-buf-cache.h、rk-dma-heap.h;drivers/dma-buf/dma-buf-cache.c |
如需,可以继续展开:dma_buf_map_attachment 的 cache_sgt_mapping/pin 交互、dma_resv 的 ww_mutex+seqcount 读写并发细节、dma_fence 的 signaling 临界区(防死锁)机制,或某个具体 heap(rk_cma_heap.c)的分配实现。