尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

第三章:GEM分析:3.2.1 gem_object 生命周期与使用流程(动态使用视角)

第三章:GEM分析:3.2.1 gem_object 生命周期与使用流程(动态使用视角) gem_object 讲对象是什么字段与结构本文以时间线为主轴把一个drm_gem_object从诞生到销毁的完整流程串起来并在每个阶段指出涉及哪些字段和哪些回调。1. 全景一个对象的一生① 创建分配 init② 暴露handle③ CPU 使用mmap④ GPU 使用VA 映射 / 提交⑤ 共享flink / dma-buf⑥ 回收压力evict / swap⑦ 销毁handle 关闭 → refcount 归零 → free贯穿全程的一条主线是 gem_object 强调的双计数refcountkref——控制对象的物理生命周期归零即freehandle_count——追踪用户态引用归零时清理 flink 名与 dma-buf 关联但不一定销毁对象。一句话记住二者关系handle 是用户态的门票refcount 是对象的生死簿。门票全退了对象未必死内核态可能还持票。当然并不是所有的对象都会走完整个生命周期例如一个对象只在内核里使用那么它就不需要暴露给用户态因此只有创建和销毁两个流程。2. 阶段①创建分配 初始化用户态通过驱动特定的 ioctl如AMDGPU_GEM_CREATE、DRM_IOCTL_MODE_CREATE_DUMB请求分配。内核侧分两步分配内存驱动kzalloc自己的对象如amdgpu_bo其中内嵌drm_gem_object见 gem_object 的驱动扩展。初始化 core 部分二选一初始化函数后端对应字段drm_gem_object_init()shmem-backed由 shmfs 提供可换出的匿名页filp ! NULLdrm_gem_private_object_init()private驱动自管存储VRAM / CMA / TTM BOfilp NULL初始化会设置dev、size此后不可变、内置_resv同步对象并把funcs指针挂上驱动的回调表。此时refcount 1但还没有 handle——对象只存在于内核。涉及回调本阶段不触发funcs里的任何回调回调表只是被挂载等后续操作时才被调用。3. 阶段②暴露给用户态handle 分配对象要被用户态使用必须换成一个handle进程内的 32 位整数。核心函数drm_gem_handle_create_tail()做三件事在该drm_file的 IDR 中分配 handlehandle_count、refcounthandle 也是一份引用调用funcs-open(obj, file)若实现。驱动回调DRM core用户态驱动回调DRM core用户态CREATE ioctl分配对象 initrefcount1handle_create → handle_count, refcountfuncs-open(obj, file)返回 handle关键点open绑定的是handle 而非对象。同一对象被多个进程 open例如经 flink/dma-buf 再GEM_OPEN就会多次触发open。amdgpu 常在此建立该drm_file的 VM × 本 BO的记账关系。涉及字段handle_count、refcount涉及回调gem_object_funcs 的open。4. 阶段③CPU 使用mmap用户态要用 CPU 读写对象内容时走 mmap。GEM 用伪偏移fake offset把mmap 一个文件的某偏移转译为映射某个 GEM 对象先DRM_IOCTL_MODE_MAP_DUMB之类拿到对象在drm_vma_offset_manager中的偏移记录在vma_node见 gem_object 2.3 和 gem设计目标 3.3mmap(drm_fd, offset)→ core 的drm_gem_mmap()按 offset 反查到对象drm_gem_mmap_obj()若实现了funcs-mmap就调它建立 VMA否则用funcs-vm_ops其fault处理缺页、按需填页。有无mmap(drm_fd, fake_offset)drm_vma_offset_manager 反查定位 drm_gem_objectfuncs-mmap ?funcs-mmap 自行建 VMA默认路径用 funcs-vm_ops访问触发 fault → 按需填页涉及字段vma_node、filpshmem 缺页从 shmfs 取页涉及回调mmap与vm_ops二者互斥见 gem_object_funcs 3.3。关于gem_ojbectmmap的详细分析请参见 用户态访问 BO 的 CPU VA的 fake offset 机制全流程解析。5. 阶段④GPU 使用地址映射与提交让 GPU 访问对象是整条演进线的核心它有新旧两种范式详见专门文档旧模型提交时带 BO-list relocation内核在提交时临时决定地址——见 gem_object 如何被 GPU 访问上。新模型VM_BIND6.6用户态显式建立持久 GPU VA 映射由drm_gpuvm/drm_gpuva框架管理对象里的gpuva字段是这些映射的反向索引——见 GEM分析gem_object 如何被 GPU 访问下与 gpuva。无论哪种范式提交执行都要挂 fence 到对象的dma_resvresv/_resv字段以保证同步——GPU 还在用时回收/迁移必须等待。涉及字段resv/_resv同步、gpuva6.6 反向索引本阶段不直接对应某个funcs回调但会与阶段⑥的evict相互作用evict 时需让指向本对象的 GPU VA 映射失效。6. 阶段⑤共享flink 与 dma-buf对象可被跨进程或跨设备共享两条路径对比见 gem设计目标 3.5路径机制相关字段 / 回调flink全局名nameGEM_FLINK分配、GEM_OPEN取回 handle不安全遗留 X11 用name字段PRIME / dma-bufPRIME_HANDLE_TO_FD导出为 dma-buf跨设备安全共享dma_buf/import_attach字段export/pin/unpin/get_sg_table/vmap回调dma-buf 被导入方 attach时core 会dma_resv_lock后调funcs-pin钉住后端存储——这是共享抑制迁移的根源见 gem_object_funcs 3.2 的时序图。注意引用循环对象导出为 dma-buf 后dma_buf与对象互相持引用core 在最后一个 handle 释放时打破这个循环见 [gem_object](https://blog.csdn.net/shenjunpeng/article/details/160797999。7. 阶段⑥回收压力evict 与 swap内存紧张时对象后端可能被换出evictdrm_gem_object_evict()在已持obj-resv的前提下调funcs-evict把后端从 VRAM 搬到系统内存或释放可重建页。GEM core 不做迁移策略只在合适时机通知驱动迁移实作通常借 TTM见 gem设计目标 第 6 节。swapshmem-backed 对象filp ! NULL的匿名页可被内核页回收换出——这是可被 swap不等于VRAM↔RAM 迁移。与 gpuva 联动evict 后指向本对象的所有 GPU VA 映射都要drm_gpuva_invalidate()驱动遍历gpuva.list见 gem_object_gpuva。涉及回调evict进入时已持 resv实现内不得重复加锁见 gem_object_funcs 第 4 节。8. 阶段⑦销毁handle 关闭 → refcount 归零 → free销毁是双计数协同的终点必须分清两个关闭驱动回调DRM core用户态驱动回调DRM core用户态handle_count0 → 清理 flink name、断开 dma_buf 关联对象存活等最后一个引用释放alt[refcount 归零][仍有内核态引用]GEM_CLOSE / 进程退出funcs-close(obj, file) (每个 handle 一次)handle_count--refcount--funcs-free(obj) (唯一必需回调析构)drm_gem_object_release() 清理 core 部分关 handledrm_gem_object_release_handle()调funcs-closehandle_count--。归零时清理 flink 名与 dma-buf 关联但对象未必死。refcount 归零这才触发funcs-free唯一必需回调驱动释放后端、drm_gem_object_release()清 core、kfree自身。最常见误解以为关了 handle 对象就没了。只要还有 mmap 映射、dma-buf 导出或内核内部引用close之后对象不会free见 gem_object_funcs 3.1 的误区提示。9. 字段 × 回调 × 阶段一张对照表阶段主要字段触发的回调深入文档① 创建dev/size/filp/_resv/funcs无gem_object② 暴露handle_count/refcountopengem_object_funcs 3.1③ CPU mmapvma_node/filpmmap/vm_opsgem_object_funcs 3.3④ GPU 使用resv/gpuva与 evict 联动⑤ 共享name/dma_buf/import_attachexport/pin/unpin/get_sg_table/vmapgem_object_funcs 3.2⑥ 回收filp/resv/gpuvaevictgem_object_funcs 3.4⑦ 销毁handle_count/refcount/name/dma_bufclose→freegem_object_funcs 3.110. 小结一个 GEM 对象的一生 创建 → 暴露(handle) → 使用(CPU/GPU) → 共享 → 回收 → 销毁全程由双计数refcount生死簿 /handle_count门票驱动。每个阶段都在用某些字段并触发某些回调本文的对照表就是 gem_object字段与 gem_object_funcs回调之间的索引。记住三条易错点handle 归零 ≠ 对象销毁共享(pin) 会抑制迁移可被 swap ≠ 支持 VRAM 迁移。
返回列表