news 2026/2/3 8:55:03

20251129 - 详细解析Linux的mmap(内存映射)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
20251129 - 详细解析Linux的mmap(内存映射)

详细解析Linux的mmap(内存映射)

mmap(Memory Map,内存映射)是 Linux 系统编程中最迷人、最强大,但也最容易出错的机制之一。

它打破了“文件是文件,内存是内存”的界限,让程序员可以像操作内存数组一样直接操作文件,甚至直接操作硬件(在嵌入式开发中尤为重要)。

以下是对mmap的全方位深度解析。

1. 核心概念:什么是内存映射?

传统read/write模型中,如果想修改文件:

  1. 内核态:内核把数据从磁盘读到内核高速缓存(Page Cache)。
  2. 拷贝:内核把数据从 Page Cache **拷贝**到用户进程的缓冲区(User Buffer)。
  3. 修改:用户在 User Buffer 修改数据。
  4. 拷贝:用户把数据拷贝回内核。
  5. 内核态:内核把数据刷回磁盘。

关键词:内核->Page Cache(页缓存)->用户缓存并修改->Page Cache(页缓存)->内核缓存->磁盘

mmap 模型:

mmap 请求内核:“请把这个文件直接‘投影’到我的虚拟内存里。”

  • 零拷贝 (Zero Copy):内核直接把文件的 Page Cache 映射到用户的虚拟地址空间。
  • 直接操作:用户进程直接读写这段内存,实际上就是在读写内核的 Page Cache。
  • 自动同步:内核负责在后台将 Page Cache 的变动刷新到磁盘。

一句话总结:mmap建立了“进程虚拟内存”与“文件对象”之间的一座桥梁。

2. 函数原型与关键参数

头文件:<sys/mman.h>

void*mmap(void*addr,size_tlength,intprot,intflags,intfd,off_toffset);
参数含义详解
addr映射起始地址通常设为NULL,让内核自动选择一块空闲地址。
length映射长度想要映射多少字节(通常是文件大小)。
prot保护权限PROT_READ(可读),PROT_WRITE(可写),PROT_EXEC(可执行),PROT_NONE(不可访问)。必须与 open 时的权限匹配。
flags映射标志关键参数!决定了内存修改是否同步回文件(见下文)。
fd文件描述符open()返回的句柄。
offset文件偏移量从文件的哪里开始映射。必须是分页大小(通常4KB)的整数倍(如 0, 4096…)。

返回值:

  • 成功:返回映射区的首地址指针。
  • 失败:返回MAP_FAILED(即(void *)-1),注意不是 NULL

3. 两种核心模式:MAP_SHAREDvsMAP_PRIVATE

这是flags参数中最关键的选择:

A.MAP_SHARED(变动是共享的)
  • 含义:你对内存的修改写回磁盘文件。
  • 可见性:其他映射了该文件的进程也能立即看到你的修改。
  • 用途
    • 文件操作:替代read/write修改文件。
    • 进程间通信 (IPC):两个进程mmap同一个文件,实现最高效的数据共享。
    • 硬件操作:嵌入式中映射/dev/mem来操作寄存器。
B.MAP_PRIVATE(写时复制,Copy-On-Write)
  • 含义:你对内存的修改不会写回磁盘文件。
  • 机制:当你第一次尝试修改数据时,内核会悄悄拷贝一份数据给你(私有副本),你修改的是副本。
  • 用途
    • 加载动态库.so文件加载到内存时,代码段是共享的,但数据段是私有的。
    • 调试器:在不破坏源文件的情况下修改内存中的程序逻辑。

4. 嵌入式开发专属:mmap操作硬件寄存器

在您的i.MX6ULL开发中,mmap是驱动开发和裸机应用的核心。

原理:

CPU 有物理地址空间,硬件外设(如 GPIO 控制器)映射在特定的物理地址上(查数据手册可知,例如 0x20AC000)。Linux 用户态程序不能直接访问物理地址,必须用 mmap 将物理地址映射成虚拟地址。

伪代码示例:

intfd=open("/dev/mem",O_RDWR);// 打开物理内存设备// 将物理地址 0x20AC000 开始的 4KB 映射到虚拟内存unsignedchar*gpio_base=mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x20AC000);// 现在可以直接操作寄存器点灯了!*(volatileunsignedint*)(gpio_base+0x04)=0xFF;// 写寄存器

5.mmapread/write的性能对比

很多初学者认为mmap总是比read/write快,这是误区

场景推荐方式原因
小文件 / 顺序读写read/writemmap建立映射和销毁映射有较大的系统开销(Setup Cost)。对于简单读写,系统调用反而更快。
大文件 / 随机读写mmapread/write需要频繁移动文件指针 (lseek) 并进行多次内存拷贝。mmap直接通过指针跳转,效率极高。
频繁修改文件mmap修改内存比调用write写入磁盘快得多。
流式数据 (Pipe/Socket)read/writemmap只能映射可定位的文件(seekable),不能映射管道或套接字。

6. 实战中的“坑”与注意事项

A. 缺页异常 (Page Fault) 是隐形成本

mmap调用返回极快,因为此时内核并没有真的把文件读入内存。

  • 当你第一次访问ptr[0]时,CPU 触发缺页异常。

  • 内核捕获异常,暂停你的进程,去磁盘读取数据到 Page Cache,修改页表。

  • 恢复进程执行。

    这意味着:mmap 是“懒加载”的。

B. 文件大小限制 (SIGBUS 错误)

mmap不能改变文件大小

  • 假设文件只有 100 字节。
  • mmap了 4096 字节(一页)。
  • 你可以读写 0~99 字节。
  • 如果你写ptr[200]:虽然它在映射的 4KB 页内,但它超过了文件实际大小。你会收到SIGBUS信号,程序崩溃。
  • 解决:mmap之前,先用lseek+write或者ftruncate()把文件撑大。
C. 同步问题

MAP_SHARED并不保证立即可靠地写入磁盘,它只是写到了内核缓存。

  • 如果系统断电,数据可能丢失。
  • 强制同步:使用msync(addr, len, MS_SYNC)函数,类似于文件 I/O 的fsync
D. 解除映射

使用完毕后,必须调用:

munmap(void*addr,size_tlength);

如果不调用,进程结束后内核才会自动回收,因此长期运行的服务会造成虚拟内存泄漏。

7. 总结代码示例

这是一个标准的用mmap修改文件的模板:

#include<sys/mman.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>intmain(){constchar*filepath="data.bin";// 1. 打开文件intfd=open(filepath,O_RDWR);if(fd<0){perror("open");return1;}// 2. 获取文件大小structstatsb;if(fstat(fd,&sb)==-1){perror("fstat");return1;}// 3. 执行内存映射// 注意:MAP_SHARED 才能写回文件char*mapped=mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(mapped==MAP_FAILED){perror("mmap");return1;}// 4. 像操作数组一样操作文件printf("Old: %c\n",mapped[0]);mapped[0]='X';// 修改内存,实际上就是修改文件// 5. (可选) 强制同步回磁盘msync(mapped,sb.st_size,MS_SYNC);// 6. 解除映射munmap(mapped,sb.st_size);// 7. 关闭文件close(fd);return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/4 2:33:19

揭秘Open-AutoGLM收益查询黑科技:3步实现自动化收益追踪

第一章&#xff1a;揭秘Open-AutoGLM收益查询黑科技&#xff1a;3步实现自动化收益追踪在数字资产管理日益复杂的今天&#xff0c;高效追踪收益成为开发者与投资者的核心需求。Open-AutoGLM 作为一款基于大语言模型的自动化工具&#xff0c;提供了精准、低延迟的收益数据抓取与…

作者头像 李华
网站建设 2026/2/2 6:32:59

为什么顶级政务部门都在悄悄部署Open-AutoGLM?(内部技术白皮书流出)

第一章&#xff1a;Open-AutoGLM在政务场景中的战略定位Open-AutoGLM作为新一代开源自动化生成语言模型&#xff0c;正逐步成为政务智能化转型的核心支撑技术。其在政策解读、公文生成、智能问答与跨部门协同等关键场景中展现出强大的适应性与扩展能力&#xff0c;为构建高效、…

作者头像 李华
网站建设 2026/2/2 21:46:52

公积金提取太慢?Open-AutoGLM智能引擎提速9倍,你试过了吗?

第一章&#xff1a;公积金提取太慢&#xff1f;Open-AutoGLM智能引擎提速9倍&#xff0c;你试过了吗&#xff1f;在传统政务系统中&#xff0c;公积金提取流程常因人工审核、多级审批和数据孤岛问题导致处理周期长达7天以上。Open-AutoGLM 是一款基于大模型自动化决策的智能引擎…

作者头像 李华
网站建设 2026/2/2 3:05:29

计算机毕业设计springboot基于微信小程序的校园招聘系统 基于微信小程序的校园招聘管理系统设计与实现 SpringBoot框架下微信小程序校园招聘系统开发与应用

计算机毕业设计springboot基于微信小程序的校园招聘系统t71ls9 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着数字化技术的飞速发展&#xff0c;校园招聘管理逐渐从传统的线…

作者头像 李华
网站建设 2026/2/1 15:10:09

揭秘Open-AutoGLM校园服务引擎:如何实现99.9%可用性的智能调度?

第一章&#xff1a;Open-AutoGLM校园服务引擎概述Open-AutoGLM 是一款专为高校场景设计的智能服务引擎&#xff0c;融合了大语言模型&#xff08;LLM&#xff09;能力与自动化流程控制机制&#xff0c;旨在提升校园管理效率、优化师生服务体验。该引擎基于 GLM 架构进行深度定制…

作者头像 李华
网站建设 2026/2/2 2:46:26

好写作AI:你的论文为什么越改越差?当心陷入“AI修改陷阱”

你有没有经历过这样的绝望循环&#xff1f;收到修改意见后&#xff0c;你让AI“让这段表述更学术”——它照做了。但接着&#xff0c;导师又说“理论深度不够”&#xff0c;你再次求助AI“加强理论深度”——它又生成一版。几轮下来&#xff0c;那段文字变得臃肿、矛盾&#xf…

作者头像 李华