尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
4.3.1 对象与创建:只有文件,没有页
4.3 论证了采用 shmem 文件作为后备的理由内容存放于文件中helper 仅按需获取页使用完毕后归还页。本节先给出 helper 的核心数据结构struct drm_gem_shmem_object的全貌再讨论drm_gem_shmem_create()创建对象时完成的工作。结论只有一句创建结束时对象拥有一个 shmem 文件但没有任何物理页。1、结构全貌该结构定义于include/drm/drm_gem_shmem_helper.hstructdrm_gem_shmem_object{structdrm_gem_objectbase;/* 内嵌的 GEM 对象 */structpage**pages;/* 从 shmem 文件获取的页 */refcount_tpages_use_count;/* pages[] 的持有者计数 */refcount_tpages_pin_count;/* pin 计数 */intmadv;/* 0 在用0 可丢弃0 已 purge */structlist_headmadv_list;/* 加入驱动的可回收链表 */structsg_table*sgt;/* 已 DMA 映射的 sg 表 */void*vaddr;/* 内核连续映射地址 */refcount_tvmap_use_count;/* vaddr 的持有者计数 */bool pages_mark_dirty_on_put:1;bool pages_mark_accessed_on_put:1;bool map_wc:1;/* 以 write-combined 方式映射 */};除base外其余字段均描述同一事项所持有的页当前处于何种状态包括是否已获取、是否被 pin、被映射为哪些形态以及能否被回收。2、base内嵌的 GEM 对象base是内嵌的结构体而非指针因此drm_gem_shmem_object的头部即为一个完整的drm_gem_object。GEM core 仅可见basehelper 获得drm_gem_object *后通过container_of取回外层结构#defineto_drm_gem_shmem_obj(obj)\container_of(obj,structdrm_gem_shmem_object,base)驱动通常再将drm_gem_shmem_object内嵌到自身的结构中形成两层内嵌见 4.3.7。3、创建入口分配与初始化分离对象刚创建时上述字段几乎均为空pages为 NULL各计数为 0。公开入口drm_gem_shmem_create()直接转调内部函数structdrm_gem_shmem_object*drm_gem_shmem_create(structdrm_device*dev,size_tsize){return__drm_gem_shmem_create(dev,size,false);}__drm_gem_shmem_create()分两步完成先分配外层对象再进行初始化。staticstructdrm_gem_shmem_object*__drm_gem_shmem_create(structdrm_device*dev,size_tsize,bool private){...sizePAGE_ALIGN(size);if(dev-driver-gem_create_object){objdev-driver-gem_create_object(dev,size);...shmemto_drm_gem_shmem_obj(obj);}else{shmemkzalloc_obj(*shmem);...objshmem-base;}ret__drm_gem_shmem_init(dev,shmem,size,private);...returnshmem;}分配可由驱动接管。驱动实现gem_create_object时helper 使用其返回的对象。驱动由此可分配内嵌了drm_gem_shmem_object的更大结构例如 virtio-gpu 的virtio_gpu_object4.3.7。初始化可单独调用。drm_gem_shmem_init()直接调用__drm_gem_shmem_init()供自行分配对象的调用者使用例如 Rust 的 GEM 绑定。private参数。普通创建传falsedma-buf 导入时传true见第 6 节。4、__drm_gem_shmem_init()的四步staticint__drm_gem_shmem_init(structdrm_device*dev,structdrm_gem_shmem_object*shmem,size_tsize,bool private){structdrm_gem_object*objshmem-base;intret0;if(!obj-funcs)obj-funcsdrm_gem_shmem_funcs;/* ① 回调表 */if(private){drm_gem_private_object_init(dev,obj,size);shmem-map_wcfalse;}else{retdrm_gem_object_init(dev,obj,size);/* ② shmem 文件 */}...retdrm_gem_create_mmap_offset(obj);/* ③ 伪偏移 */...INIT_LIST_HEAD(shmem-madv_list);if(!private)mapping_set_gfp_mask(obj-filp-f_mapping,/* ④ GFP 掩码 */GFP_HIGHUSER|__GFP_RETRY_MAYFAIL|__GFP_NOWARN);return0;...}① 回调表drm_gem_shmem_funcs是 helper 预置的一套drm_gem_object_funcsfree、pin、unpin、get_sg_table、vmap、vunmap、mmap、vm_ops都指向 helper 的实现。该赋值的条件为if (!obj-funcs)若驱动已在gem_create_object中设置了自身的回调表helper 不会将其覆盖4.3.7。② 建立 shmem 文件drm_gem_object_init()位于 GEM coredrm_gem.c不属于 helperintdrm_gem_object_init(structdrm_device*dev,structdrm_gem_object*obj,size_tsize){structvfsmount*huge_mnt;structfile*filp;constvma_flags_tflagsmk_vma_flags(VMA_NORESERVE_BIT);drm_gem_private_object_init(dev,obj,size);huge_mntdrm_gem_get_huge_mnt(dev);if(huge_mnt)filpshmem_file_setup_with_mnt(huge_mnt,drm mm object,size,flags);elsefilpshmem_file_setup(drm mm object,size,flags);...obj-filpfilp;return0;}shmem_file_setup()在内核内部的 tmpfs 上创建一个没有路径的文件并设置到obj-filp。文件大小即对象大小此后不再改变文件在drm_gem_object_release()中随对象一起释放与创建它的进程无关。此即 4.3 第 3.1 节所述的「必选层满足」。此时尚未分配任何物理页。shmem_file_setup()仅建立了一个可按偏移取页的容器address_space已就位page cache 仍为空。页要等到 4.3.2 的get_pages才获取。若驱动事先调用drm_gem_huge_mnt_create()为设备挂载了启用 THP 的 tmpfs文件即创建于该挂载点上此后获取的页可能为 PMD 大小的 foliommap 缺页时可按大页插入4.3.4。③ 伪偏移drm_gem_create_mmap_offset()在设备的drm_vma_offset_manager中为对象分配一段伪偏移用户态以该偏移调用mmap。这是第三章 3.3 节所述的 GEM 通用机制shmem helper 直接复用。伪偏移在 shmem helper 中有两处用途mmap 时据此找到对象4.3.4purge 时被回收4.3.6。④ GFP 掩码设备层的第一处修补mapping_set_gfp_mask(obj-filp-f_mapping,GFP_HIGHUSER|__GFP_RETRY_MAYFAIL|__GFP_NOWARN);该步骤修改的是address_space的gfp_mask即「此后从该文件分配页时使用的标志」。源码注释说明了其理由Our buffers are kept pinned, so allocating them from the MOVABLE zone is a really bad idea, and conflicts with CMA.GFP_HIGHUSER不含__GFP_MOVABLE。shmem 文件的页默认从可迁移区域分配而这些页将被 helper 长期持有并供设备访问若位于可迁移区域会妨碍内存规整并与 CMA 冲突__GFP_RETRY_MAYFAIL尽力重试但允许最终失败避免大缓冲分配触发 OOM killer__GFP_NOWARN分配失败时不打印警告由上层处理错误。5、private导入对象不创建文件private为 true 时调用drm_gem_private_object_init()不创建 shmem 文件也不设置 GFP 掩码。该路径用于 dma-buf 导入页由导出方提供本地无需后备4.3.5。此时map_wc被置为 false源码注释给出的理由是 dma-buf 映射总是使用 write-combine由导出方决定。6、销毁与创建对称销毁路径drm_gem_shmem_release()对本地对象的处理恰好按相反顺序撤销创建与使用过程中建立的各项资源voiddrm_gem_shmem_release(structdrm_gem_shmem_object*shmem){structdrm_gem_object*objshmem-base;if(drm_gem_is_imported(obj)){drm_prime_gem_destroy(obj,shmem-sgt);}else{dma_resv_lock(shmem-base.resv,NULL);...if(shmem-sgt){/* 设备映射 */dma_unmap_sgtable(obj-dev-dev,shmem-sgt,DMA_BIDIRECTIONAL,0);sg_free_table(shmem-sgt);kfree(shmem-sgt);}if(shmem-pages)drm_gem_shmem_put_pages_locked(shmem);/* 所持有的页 */...dma_resv_unlock(shmem-base.resv);}drm_gem_object_release(obj);/* shmem 文件与伪偏移 */}helper 默认回调表中的free为drm_gem_shmem_object_free()该函数调用drm_gem_shmem_free()后者即drm_gem_shmem_release()加上对象本身内存的释放。7、本节小结drm_gem_shmem_object头部内嵌drm_gem_object对象身份、resv、伪偏移、后备文件均由base提供其余字段均围绕「所持有的页处于何种状态」组织。创建分为分配与初始化两步分配可由驱动通过gem_create_object接管。初始化四步设置回调表、建立 shmem 文件、分配伪偏移、设定 GFP 掩码。导入对象走private路径不建文件。创建结束时只有文件没有页。下一节4.3.2页何时、如何从 shmem 文件中取出又如何归还以及这些操作共同依赖的那把锁。
RELATED

相关推荐

华为云码道实战:用 Vue 3 + Three.js 实现六面祝福宫灯与 GIF 导出

华为云码道实战:用 Vue 3 + Three.js 实现六面祝福宫灯与 GIF 导出

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/27 18:42:44
把火灵珠放进 ABAP 系统,得到的会是什么

把火灵珠放进 ABAP 系统,得到的会是什么

冷链仓库里有一批药品,传感器每隔几分钟上传一次温度。上午十点,某个库位的读数越过预警线;再过一段时间,另一条读数越过了必须拦截出库的界限。此时,仓库主管需要看到异常,出库流程需要知道货物能否放行,后台还需要保存处理记录。倘若这三处各写一套温度判断,迟早会出…

📅 2026/10/27 18:42:44
基于Java的非遗文化交流与分享网站(Java+SSM+MySQL)| 毕业设计 源码+论文+完整教程

基于Java的非遗文化交流与分享网站(Java+SSM+MySQL)| 毕业设计 源码+论文+完整教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/27 18:42:44
MORE NEWS

更多资讯

📰

中文影评情感分析系统:BiLSTM-CRF工程实践指南

1. 项目概述:这不是一个“跑通模型”的作业,而是一次真实场景下的端到端工程实践“毕业设计:基于深度学习的电影评论情感分析系统”——这个标题在每年春季的高校毕设选题表里高频出现,但真正能跑出可用结果、经得起用户随手输入一…

📰

二维数组与函数:编程基础与性能优化实战

1. 二维数组与函数的基础概念解析 在编程世界中,二维数组和函数是两个最基础也最重要的概念。二维数组就像是Excel表格,有行有列,可以整齐地存放数据;而函数则像是工厂里的机器,接收原料(参数)&…

📰

Flink流原生架构与生产级容错实践指南

1. 为什么Flink的“流原生”不是一句口号,而是整套架构的呼吸节奏很多人第一次接触Flink时,看到“流式处理引擎”这个标签,下意识会把它和Kafka Consumer 自定义业务逻辑的组合划等号——不就是从消息队列里拉数据、做点计算、再写回去吗&am…

📰

基于YOLOv8的手势识别系统开发与优化实践

1. 项目概述:基于YOLOv8的手势识别系统全流程实现这个手势识别系统完整实现了从数据标注到模型训练再到Web展示的全链路开发流程。核心采用YOLOv8目标检测算法,针对石头剪刀布手势进行专项优化,配套提供标注好的数据集和70改进方案。不同于市…

📰

人大金仓V9 Windows初始化失败:sys_ctl报‘不是数据库集群目录’的根因与修复

简介:本资源是一份面向Windows平台数据库工程师、运维人员及信创项目实施者的实操指南,系统讲解人大金仓Kingbase V9在Windows环境下的全流程部署与基础管理。内容覆盖官方下载路径、安装避坑要点(如禁用空格路径、关闭杀毒软件)、…

📰

OpenClaw开源AI技术在小龙虾养殖中的应用与部署指南

1. OpenClaw技术革命:从实验室到虾塘的跨越 OpenClaw最初是2022年出现在GitHub上的一个开源AI项目,核心代码采用Python编写,基于PyTorch框架构建。这个看似普通的代码库却在农业领域掀起了一场风暴——它首次将计算机视觉和强化学习技术成功应…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬