news 2026/10/23 9:46:55

Linux应用与驱动开发:mmap和内存映射

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux应用与驱动开发:mmap和内存映射

学习笔记:Linux 驱动开发之mmap与内存映射

1. 核心概念:什么是mmap?

mmap(Memory Map) 是一种内存映射文件的方法。在嵌入式 Linux 驱动开发中,它主要用于将外设的物理地址(如 GPIO 寄存器)映射到用户进程的虚拟地址空间。

  • 传统方式:用户态read/write<–> 内核态拷贝数据 <–> 驱动操作寄存器。
  • mmap 方式:用户态指针 <–> MMU 直接转换 <–> 硬件寄存器。(零拷贝,速度极快)

2. 核心难点:用户虚拟地址 vs 内核虚拟地址

这是理解 Linux 内存管理的关键分水岭。

2.1 对比图表

特性用户虚拟地址 (UVA)内核虚拟地址 (KVA)
定义应用程序看到的地址。操作系统内核驱动看到的地址。
地址范围 (32位)0x00000000~0xBFFFFFFF(0~3G)0xC0000000~0xFFFFFFFF(3G~4G)
可见性私有。进程A和进程B的0x1000互不相干。全局共享。所有进程进入内核态后看到的都是同一份。
映射工具mmap()ioremap()
访问权限仅当前进程有效,进程结束即销毁。系统启动即存在,只有内核代码可读写。
物理对应通常不连续,按需分配(缺页中断)。逻辑地址线性映射,vmalloc/ioremap非线性。

2.2 它们与物理地址的关系

假设 i.MX6ULL 的一个 LED 寄存器物理地址是0x0209C000:

  1. CPU/MMU:只认物理地址0x0209C000。
  2. 驱动程序 (KVA):通过ioremap拿到一个地址(如0xF0001000)。驱动写0xF0001000-> MMU 查表 -> 写入物理地址。
  3. 应用程序 (UVA):通过mmap拿到一个地址(如0xB7001000)。应用写0xB7001000-> MMU 查表 -> 写入物理地址。

结论:UVA 和 KVA 就像是通往同一个房间(物理地址)的两扇不同的门。一扇门开在“用户公寓”(0-3G),另一扇门开在“管理员办公室”(3-4G)。


3.mmap的实现流程(驱动与应用配合)

3.1 应用程序做了什么?

应用程序中的mmap最终会调用驱动中实现的.mmap接口(即下面的my_driver_mmap函数)

int fd = open("/dev/my_led", O_RDWR); // 申请映射:从 offset 0 开始,映射 4096 字节 unsigned char *addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); // 直接操作硬件! *addr = 0x01; // 点灯

3.2 驱动程序做了什么? (fops.mmap)

驱动的核心任务是构建页表。

  1. 获取物理地址:知道你要操作哪个寄存器(例如0x0209C000)。
  2. 计算页帧号 (PFN):Linux 内存管理以“页”为单位(通常 4KB)。
    • PFN = 物理地址 >> PAGE_SHIFT(即除以 4096)。
  3. 调用remap_pfn_range:这是核心函数。它负责修改当前进程的页表,建立 UVA 到 物理地址 的映射。
// 驱动代码示例 static int my_driver_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long phy_addr = 0x0209C000; // 硬件物理地址 // 关键:设置为不使用缓存 (Nocache)!否则寄存器读写会出错 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); // 建立映射:把 vma->vm_start (应用层的UVA) 映射到 phy_addr (物理地址) if (remap_pfn_range(vma, vma->vm_start, // 用户虚拟地址起始 phy_addr >> PAGE_SHIFT, // 物理地址页帧号 vma->vm_end - vma->vm_start, // 映射大小 vma->vm_page_prot)) // 属性:无缓存 { return -EAGAIN; } return 0; }

4. 关键细节与注意事项

4.1 为什么要pgprot_noncached?

  • 原因:对于硬件寄存器,必须禁止 CPU 缓存 (Cache)。
  • 后果:如果不加这一行,应用程序写数据可能只写到了 Cache 里,LED 灯根本不会亮,或者读取的状态是旧的。

4.2 为什么映射大小通常是 4KB (4096)?

  • MMU 管理内存的最小单位是一页 (Page),ARM Linux 默认页大小是 4096 字节。
  • 即使你只需要操作 4 个字节的寄存器,mmap也会映射整整一页(4096 字节)。因此,你在计算偏移量时要小心。

4.3ioremap和mmap的关系

  • 驱动程序自己要访问寄存器 -> 用ioremap。
  • 驱动程序想让应用程序直接访问寄存器 -> 实现.mmap接口(内部调用remap_pfn_range)。
  • 通常一个驱动里这两个都会用到。

5. 总结

  1. 物理地址是唯一的真理,但被 CPU 藏在了 MMU 后面。
  2. KVA (内核虚拟地址)是驱动在内核态用的,通过ioremap映射。
  3. UVA (用户虚拟地址)是应用在用户态用的,通过mmap系统调用请求,由驱动协助映射。
  4. remap_pfn_range是连接 UVA 和 物理地址 的桥梁。

下一步实践建议:

在韦东山的开发板上,你可以写一个简单的程序,利用 /dev/mem 这个系统自带的驱动节点。它已经实现了 mmap 功能。你可以尝试用 mmap 映射 GPIO 的物理基地址,然后在应用层直接点亮 LED,这将是你理解这一概念最直观的实验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 17:57:52

PostgreSQL 图数据库化方案:Apache AGE 的引入与实践

一、介绍图数据库擅长处理复杂关联关系&#xff0c;而 PostgreSQL 擅长事务型数据管理。Apache AGE 通过扩展方式将图数据库能力引入 PostgreSQL&#xff0c;使其在保持原有稳定性与生态优势的同时&#xff0c;补齐了图数据建模与查询能力的短板。这种“关系型数据库 图模型”…

作者头像 李华
网站建设 2026/10/21 20:50:12

【倒计时一天】2025第八届金猿大数据产业发展论坛——暨AI InfraData Agent趋势论坛丨颁奖典礼·上海

第八届金猿颁奖典礼“重要提示➩ 活动报名&现场签到有好礼&#xff0c;先到先得点此小程序链接可报名参会大数据产业创新服务媒体——聚焦数据 改变商业数智产业正站在变革的临界点上。过去十年&#xff0c;大数据从技术概念演进为基础设施&#xff0c;完成了产业奠基&…

作者头像 李华
网站建设 2026/10/19 13:00:31

Figma中文插件完全配置指南:告别英文界面困扰

Figma中文插件完全配置指南&#xff1a;告别英文界面困扰 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma复杂的英文界面而头疼吗&#xff1f;面对专业设计工具&#xff0c;…

作者头像 李华
网站建设 2026/10/21 18:30:19

Figma中文界面本地化:设计师专属的语言解决方案

Figma中文界面本地化&#xff1a;设计师专属的语言解决方案 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 语言障碍的痛点与解决方案 对于国内设计从业者而言&#xff0c;Figma作为专…

作者头像 李华
网站建设 2026/10/22 11:03:05

Day 33:【99天精通Python】日志记录 (Logging) - 告别 Print 调试

Day 33&#xff1a;【99天精通Python】日志记录 (Logging) - 告别 Print 调试 前言 欢迎来到第33天&#xff01; 在之前的编程练习中&#xff0c;当我们需要调试代码或者查看程序运行状态时&#xff0c;最常用的办法就是 print()。 但是在真正的项目开发&#xff08;尤其是服务…

作者头像 李华
网站建设 2026/10/19 12:23:55

基于STSW-LINK007工具的STLink升级实战案例

STLink固件升级实战&#xff1a;从避坑到精通的完整指南 在嵌入式开发的世界里&#xff0c;调试器就像医生的听诊器——看不见它的时候风平浪静&#xff0c;一旦“连不上”、“下不进程序”&#xff0c;整个项目进度立刻停摆。而当你发现原因竟是 调试器固件太老不支持新芯片…

作者头像 李华