第三章:GEM分析 3.3 CPU 视图:从 mmap offset 到 mmap

本文是drm_gem_object三类访问视图中的第一类(三类视图的划分见 GEM 概述 §4)。这一视图的访问方是用户态进程的 CPU,入口是对 DRM 设备 fd 的mmap(2);对象内承载它的字段是vma_node,对象外的协作者是设备级的drm_vma_offset_manager及其底层的drm_mm范围分配器。

1. 为什么需要伪偏移

mmap(2)只接受一个 fd 和一个文件内偏移。同一进程的所有 GEM 对象共享同一个 DRM 设备 fd,仅凭 fd 无法指明要映射哪个对象,handle 又是进程私有的整数,不能直接放进 mmap 的参数。

GEM 的做法是在设备级维护一个偏移空间:为每个需要 CPU 映射的对象在其中分配一段按页对齐的区间,记录在obj->vma_node中;用户态把这段区间的起始地址作为 mmap 的 offset 传入,内核再按 offset 反查对象。这个偏移不对应任何物理地址,只是设备 fd 偏移空间中的一个键,因此称为伪偏移(fake offset)。

偏移空间由drm_gem_init()以DRM_FILE_PAGE_OFFSET_START和DRM_FILE_PAGE_OFFSET_SIZE初始化,在 64 位系统上从字节偏移 4 GiB 处开始,大小约 1 TiB,内部由drm_mm管理区间分配。

2. 用户态:两步调用

以 dumb buffer 为例,CPU 映射分两步:先用 ioctl 取得伪偏移,再以该偏移调用 mmap。

// include/uapi/drm/drm_mode.hstructdrm_mode_map_dumb{__u32 handle;// 输入:GEM handle__u32 pad;__u64 offset;// 输出:mmap 使用的伪偏移};/* 第一步:取得伪偏移 */structdrm_mode_map_dumbmap={.handle=handle};intret=drmIoctl(fd,DRM_IOCTL_MODE_MAP_DUMB,&map);/* 第二步:以伪偏移调用 mmap */void*ptr=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,map.offset);

GPU 驱动通常另有私有 ioctl 完成第一步,例如 amdgpu 的DRM_IOCTL_AMDGPU_GEM_MMAP(union drm_amdgpu_gem_mmap,偏移由out.addr_ptr返回)。两者返回的都是obj->vma_node在偏移空间中的起始地址,第二步完全相同。

与创建、销毁 dumb buffer 的 ioctl 一样,MAP_DUMB不带DRM_RENDER_ALLOW,在 render node 上返回-EACCES;驱动私有的 mmap ioctl 一般允许在 render node 上使用。

3. 第一步:取得伪偏移

drm_mode_mmap_dumb_ioctl()→drm_mode_mmap_dumb()[未实现 dumb_create 时返回-ENOSYS]→ driver->dumb_map_offset()[驱动提供时使用,如 amdgpu_mode_dumb_mmap]→ 否则drm_gem_dumb_map_offset()[通用实现]→drm_gem_object_lookup()[handle → obj,refcount 加一]→drm_gem_is_imported(obj)?[导入对象返回-EINVAL]→drm_gem_create_mmap_offset()[vma_node 尚未分配时在偏移空间中插入区间]→drm_vma_node_offset_addr(&obj->vma_node)→drm_gem_object_put()

几个要点:

  • 分配是惰性且幂等的。drm_vma_offset_add()在drm_mm_node_allocated()为真时直接返回,因此同一对象多次调用MAP_DUMB得到同一个偏移。通用实现在首次请求时才分配区间;TTM 则在ttm_bo_init_reserved()中对ttm_bo_type_device与ttm_bo_type_sg类型的 BO 立即分配,amdgpu 的amdgpu_mode_dumb_mmap()只读取已有偏移。
  • 驱动可以拒绝 CPU 映射。amdgpu_mode_dumb_mmap()对 userptr BO 和带AMDGPU_GEM_CREATE_NO_CPU_ACCESS标志的 BO 返回-EPERM。
  • 通用实现拒绝导入对象。导入对象的后备存储属于导出方,CPU 访问应当经 dma-buf fd 的 mmap 进行,见本章 3.5 的“与另外两类视图的衔接”。

4. 第二步:mmap 反查对象

DRM 设备 fd 的file_operations.mmap通常为drm_gem_mmap()(amdgpu 的amdgpu_driver_kms_fops也是如此):

sys_mmap()→drm_gem_mmap()→drm_gem_object_lookup_at_offset(filp,vma->vm_pgoff,vma_pages(vma))→drm_vma_offset_lock_lookup()→drm_vma_offset_exact_lookup_locked()[要求 vm_pgoff 恰为某个区间的起始页]→kref_get_unless_zero(&obj->refcount)[对象正在释放时视为不存在,返回-EINVAL]→drm_vma_offset_unlock_lookup()→drm_vma_node_is_allowed(node,priv)[当前 drm_file 无权限时返回-EACCES]→drm_gem_mmap_obj(obj,drm_vma_node_size(&obj->vma_node)<<PAGE_SHIFT,vma)→ 映射长度超过对象大小时返回-EINVAL →drm_gem_object_get(obj)[该 VMA 持有一个对象引用,vm_close 时释放]→ vma->vm_ops=funcs->vm_ops → 有 funcs->mmap:由驱动建立映射 → 否则:设置 VM_IO|VM_PFNMAP|VM_DONTEXPAND|VM_DONTDUMP 与 write-combine 页属性,缺页时由 vm_ops->fault 填页 →drm_gem_object_put(obj)[释放 lookup 取得的引用]

funcs->mmap与funcs->vm_ops的分工见 gem_object_funcs 第 4 节。

5. 权限与生命周期

谁能映射。vma_node内部维护一棵允许访问的drm_file树:drm_gem_handle_create_tail()调用drm_vma_node_allow()把当前drm_file加入,drm_gem_object_release_handle()调用drm_vma_node_revoke()将其移除。因此只有持有该对象 handle 的drm_file才能映射它,伪偏移本身不需要保密,其他进程即使得知偏移值也会在drm_vma_node_is_allowed()处被拒绝。

映射与 handle 的关系。drm_gem_mmap_obj()让每个 VMA 持有一个对象引用,所以关闭 handle 之后,已建立的映射仍然有效,对象至少要等到munmap之后才可能释放。这是 gem_object 生命周期 第 8 节“关了 handle 对象未必销毁”的典型情形。

后备存储移动时。对象被迁移或换出时,已建立的 CPU 页表项必须失效,下次访问重新缺页。偏移空间的所有映射都挂在设备的address_space上,驱动可调用drm_vma_node_unmap()按该对象的偏移区间执行unmap_mapping_range(),TTM 在ttm_bo_unmap_virtual()中即是如此。

6. 本节各篇

小节内容
3.3.1 drm_vma_offset_manager:偏移窗口与访问控制三个结构、用到的drm_mm接口、区间与允许列表的 API、查找与释放的竞争
3.3.2 amdgpu 的 CPU 映射:从 GEM_MMAP 到缺页TTM 创建时分配偏移、mmap 的三层叠加、不可见 VRAM 的缺页处理、搬迁后的映射失效

偏移窗口底层的drm_mm是 DRM 的通用范围分配器,vma manager 只用到它的一小部分(3.3.1 第 2 节)。它的完整设计与实现放在第 5 章,与drm_buddy对照阅读:drm_mm 范围分配器:设计与接口、drm_mm 实现分析。

相关新闻

Vue集成高德地图实时定位全链路实践:坐标纠偏、兼容性与降级方案

Vue集成高德地图实时定位全链路实践:坐标纠偏、兼容性与降级方案

简介&#xff1a;本资源是一份轻量级 Vue 前端集成方案&#xff0c;面向 Web 开发初学者与中级前端工程师&#xff0c;解决在 Vue 项目中快速接入高德地图并实现用户实时定位的核心需求。资源包仅含 2 个关键文件&#xff08;1 个 JS 封装脚本 1 个 Vue 组件&#xff09;&…

2026/10/20 2:16:26 阅读更多 →
OpenCV虚拟键盘:面向残障用户的轻量级视觉交互方案

OpenCV虚拟键盘:面向残障用户的轻量级视觉交互方案

1. 这个“虚拟键盘”到底在解决什么真实问题&#xff1f;很多人看到“OpenCV 视频虚拟键盘”第一反应是&#xff1a;又一个炫技Demo&#xff1f;不敲实体键也能打字&#xff1f;听起来像实验室里的玩具。但我在带某高校人机交互课程时&#xff0c;连续三年观察到一个被反复忽略…

2026/10/20 2:16:26 阅读更多 →
从Java后端到AI Agent:3个月上岸大厂经验分享,小白也能收藏这份学习路线图

从Java后端到AI Agent:3个月上岸大厂经验分享,小白也能收藏这份学习路线图

本文分享了一位四年Java后端开发者转行Agent开发的完整经历&#xff0c;包括学习路径、面试准备和职场感悟。作者通过3个月系统学习&#xff0c;成功入职大厂AI Agent团队。文章强调Agent开发需要后端工程能力&#xff0c;如并发、系统设计等&#xff0c;并提供了六层学习框架和…

2026/10/20 2:15:25 阅读更多 →

最新新闻

从URL取参到Cookie操作:前端开发完整指南与踩坑记录

从URL取参到Cookie操作:前端开发完整指南与踩坑记录

老读者可能还记得&#xff0c;我之前在某公司的运营后台系统里做过一次页面重构&#xff0c;其中有个特别不起眼但又绕不开的需求&#xff1a;从前端拿 URL 上携带的参数&#xff0c;顺手把一些状态写进 Cookie。听起来简单&#xff0c;真正动手的时候才发现&#xff0c;这里面…

2026/10/20 2:54:46 阅读更多 →
不复杂的复杂度:Java开发者必备的大O分析指南

不复杂的复杂度:Java开发者必备的大O分析指南

第八篇了。前面我们用了几篇的篇幅&#xff0c;把Java的语法、面向对象、集合框架、I/O、异常这些基础内容过了一遍。今天想插一个看起来不太一样、但实际非常重要的主题——复杂度分析。为什么在这个节点讲它&#xff1f;因为我发现很多人在前面那些内容学完之后&#xff0c;开…

2026/10/20 2:54:46 阅读更多 →
需求分级与优先级管理:产研团队高效协作的落地指南

需求分级与优先级管理:产研团队高效协作的落地指南

周五下午三点&#xff0c;我正在跟团队过下一迭代的排期。会议室的门被推开&#xff0c;某业务线负责人带着一份PPT走进来&#xff0c;说有一位大客户急需一个定制功能&#xff0c;客户已经在催&#xff0c;下周要看到演示&#xff0c;否则可能影响续约。会议室安静了几秒&…

2026/10/20 2:54:46 阅读更多 →
降AI率工具实测:九类工具原理、风险与一套可复用工作流

降AI率工具实测:九类工具原理、风险与一套可复用工作流

开头部分可以这么写&#xff1a;最近不少本科生来找我看论文初稿&#xff0c;十份里有八份开头都是“随着社会的不断发展”&#xff0c;第二段必是“综上所述”。一问才知道&#xff0c;都是让AI先写一版&#xff0c;自己再改&#xff0c;改完一检测&#xff0c;“AI率”飙到百…

2026/10/20 2:54:46 阅读更多 →
Llama 2 提示词完全指南:模板、参数与实战技巧

Llama 2 提示词完全指南:模板、参数与实战技巧

最近几周我一直在折腾基于 Llama 2 的几个实际项目&#xff0c;从本地部署到 API 接入都走了一遍。反复试下来发现一个很多人容易忽略的事实&#xff1a;Llama 2 和 GPT 系列这类闭源模型的对话习惯差异非常大&#xff0c;直接把原来惯用的提示词搬过去&#xff0c;效果会肉眼可…

2026/10/20 2:54:46 阅读更多 →
大模型Skills应用实战:在Trae中把提示词变成可复用工作流

大模型Skills应用实战:在Trae中把提示词变成可复用工作流

这个系列写到第14篇&#xff0c;我聊点真正能提效的东西——大模型Skills应用。之前几篇要么在讲模型能力边界&#xff0c;要么在讲上下文工程&#xff0c;这次把视角落到一个具体场景&#xff1a;在Trae这款AI原生IDE里&#xff0c;怎么把Skill从"听说过"变成"…

2026/10/20 2:53:45 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/18 12:16:16 阅读更多 →