Linux驱动子系统:DMA-Buf —— Consumer和Provider(008)

深入理解 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 内核里用于跨设备、跨进程共享内存缓冲区的核心框架。它看起来只是"共享一块内存",但一旦进入内核,就会遇到八类复杂问题:

  1. 跨设备共享:GPU 分配的内存要给显示控制器、视频编解码器、NPU、摄像头同时使用。
  2. 跨进程传递:一个进程分配的缓冲区要传给另一个进程,传统共享内存做不到设备级语义。
  3. 零拷贝:数据不能在各设备间复制,必须共享同一块物理内存。
  4. DMA 映射差异:不同设备有不同的 DMA 地址空间、IOMMU 映射、cache 属性。
  5. 同步:谁在用、谁在写、何时可复用,必须有 fence 语义。
  6. CPU 访问一致性:CPU 与设备访问同一块内存,cache 必须同步。
  7. 生命周期:缓冲区被多个设备、多个进程引用,释放时机必须精确。
  8. 分配策略差异: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 同步。
  • Coredma-buf.cdma-fence.cdma-resv.cdma-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 可以 mmappolldup
  • 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-cacherk_cma_heap 扩展

1.9 设计原则总结

  1. fd 即句柄:跨进程传递,VFS 统一管理。
  2. Exporter/Importer 分离:内存与使用解耦。
  3. attach / map 两阶段:关系与映射分离。
  4. fence 同步:时间线 + seqno,跨设备通用。
  5. reservation 簿记:独占/共享 fence 表,ww_mutex 防死锁。
  6. CPU 访问契约:begin/end_cpu_access 包裹。
  7. 分配策略可插拔: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/putdma_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_bufdma_buf_attachmentdma_buf_opsdma_buf_export_info
include/linux/dma-fence.h dma_fencedma_fence_opsdma_fence_cb
include/linux/dma-resv.h dma_resvdma_resv_listdma_resv_iter
include/linux/dma-heap.h dma_heap_opsdma_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 的职责

  1. 维护 dma_buf 生命周期:dma_buf_export() / dma_buf_get() / dma_buf_put()
  2. 管理 fd:dma_buf_fd() 安装 anon file。
  3. 管理 attachments:dma_buf_attach() / detach()
  4. 管理映射:dma_buf_map_attachment() / unmap_attachment()
  5. 管理 CPU 访问:begin_cpu_access / end_cpu_access
  6. 管理 vmap/mmap。
  7. 提供 ioctl:SYNC / SET_NAME / GET_FLAGS / GET_UUID
  8. 提供 poll。
  9. 提供 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_exclfence 分离,写者与读者分别管理。

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_fencecb_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_lockdma_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_chaindma_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 验证步骤

  1. ls /dev/dma_heap/ 确认 heap 注册;
  2. cat /sys/kernel/dmabuf/buffers 确认 buffer 统计;
  3. 分配一个 buffer,确认 fd 有效;
  4. dma_buf_get(fd) 拿到句柄;
  5. dma_buf_attach + dma_buf_map_attachment 确认 sg_table;
  6. dma_resv_wait_timeout_rcu 验证 fence 同步;
  7. 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 的关键是抓住四条线:

  1. 句柄线dma_buf_fd() → fd → dma_buf_get()dma_buf_put()
  2. 映射线dma_buf_attach()dma_buf_map_attachment()sg_tabledma_buf_unmap_attachment()
  3. 同步线dma_fencedma_resvadd_excl/shared_fencewait_timeout_rcu
  4. 分配线dma_heap_add()dma_heap_ops->allocate()dma_buf_export()

掌握这四条线,再看 dma-buf.cdma-fence.cdma-resv.cdma-heap.c 和 Rockchip 的 rk_cma_heap.c / dma-buf-cache.c,就能把 DMA-BUF 子系统串起来。


附:关键源码位置速查

主题 位置
核心对象/ops include/linux/dma-buf.hdma_buf_ops:36、dma_buf:410、dma_buf_attachment:511、dma_buf_export_info:540)
核心实现 drivers/dma-buf/dma-buf.cdma_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.hdma_fence:65、dma_fence_ops:125);drivers/dma-buf/dma-fence.c
resv include/linux/dma-resv.h:70drivers/dma-buf/dma-resv.c
heap include/linux/dma-heap.hdrivers/dma-buf/dma-heap.cheaps/{system,cma,rk_cma,sram}_heap.c
fence 复合 drivers/dma-buf/dma-fence-array.cdma-fence-chain.c
用户态同步 drivers/dma-buf/sync_file.csw_sync.c
Rockchip 扩展 include/linux/dma-buf-cache.hrk-dma-heap.hdrivers/dma-buf/dma-buf-cache.c

如需,可以继续展开:dma_buf_map_attachmentcache_sgt_mapping/pin 交互、dma_resv 的 ww_mutex+seqcount 读写并发细节、dma_fence 的 signaling 临界区(防死锁)机制,或某个具体 heap(rk_cma_heap.c)的分配实现。

相关推荐
雯宝2 小时前
Linux 内核函数集
linux
GeW2 小时前
从挂科到高分通过:RHCE快速拿证的10个提分技巧
linux
鸠摩智首席音效师3 小时前
Linux /etc/nsswitch.conf 文件有什么作用 ?
linux
东城居士3 小时前
理解pinctrl和gpio子系统驱动
linux·嵌入式系统
H_oRIZoN_3 小时前
Linux入门DAY43 ARM 架构基础、寄存器、大小端、异常向量、交叉编译
linux·arm·linux应用编程
国产HT1621B4 小时前
显示省不了电,休眠才见真章:1621 低功耗实操
驱动开发·单片机·嵌入式硬件·led驱动·lcd驱动
ι:4 小时前
NUC12 Pro 安装 Ubuntu 24.04 LTS 详细教程
linux·windows·ubuntu·nuc
代码村新手5 小时前
Linux-进程概念
linux
ShineWinsu5 小时前
对于Git:基础操作的超详细保姆级解析
linux·c++·git·面试·备份·管理·版本控制器