news 2026/6/22 12:43:12

Linux----mmap

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux----mmap

在学习 Linux 内存管理、多线程或高性能 I/O 时,mmap()是一个绕不开的系统调用。很多人第一次接触它,都会把它理解成“另一种 malloc”,但实际上mmap 是 Linux 虚拟内存机制中最核心、最基础的接口之一

本文将从是什么、能做什么、怎么用、为什么重要四个层次,系统地梳理 mmap。


一、一句话理解 mmap

mmap()的本质不是“分配内存”,而是建立一段虚拟地址空间与某种资源之间的映射关系。

这里的“资源”可以是:

  • 磁盘文件

  • 匿名内存(不对应任何文件)

  • 设备(如共享内存、显存等)

一旦映射建立,程序就可以像访问普通内存一样访问这些资源


二、mmap 在 Linux 中处于什么位置?

从抽象层次看:

应用程序 ↓ libc (malloc / fopen / pthread) ↓ mmap / brk / read / write ← 关键接口 ↓ 虚拟内存系统(页表 / 缺页异常) ↓ 物理内存 / 磁盘 / 设备

mmap 是连接“用户程序”与“虚拟内存系统”的桥梁


三、mmap 的两种核心用法

文件映射(File-backed mapping)

int fd = open("data.bin", O_RDONLY); void *addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);

含义:

  • 把文件的一部分映射进进程地址空间

  • 对内存的访问 ≈ 对文件的访问

特点

  • 不需要read()/write()

  • 利用页缓存,按需加载

  • 支持零拷贝

典型应用

  • 加载共享库(.so

  • 大文件随机访问

  • 数据库、搜索引擎


匿名映射(Anonymous mapping)

void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

含义:

  • 映射一段“无来源”的内存

  • 不对应任何磁盘文件

这正是:

  • 线程栈

  • 大块动态内存

  • 共享内存

的底层来源。


四、mmap 和 malloc 的关系

这是一个经典问题。

对比项mallocmmap
层级库函数系统调用
小内存使用 brk 扩展堆不适合
大内存内部直接用 mmap非常适合
回收可能延迟munmap 立即释放
碎片容易产生相对较少

glibc 的 malloc 在分配大块内存时,本身就会调用 mmap。


五、为什么 mmap 不“立刻占用”物理内存?

这是理解虚拟内存的关键。

mmap → 建立映射关系 访问 → 缺页异常 缺页 → 分配物理页

特点:

  • mmap 本身几乎是 O(1)

  • 物理内存按需分配

  • 未访问的映射不消耗 RAM

这也是 mmap高效、可扩展的根本原因。


六、mmap 与多线程:线程栈从哪里来?

在 Linux 中:

  • 主线程栈:由内核在execve时建立

  • 新线程栈:

    • 由 pthread 库

    • 使用mmap(MAP_ANONYMOUS)分配

/proc/<pid>/maps中常见:

7ffde9c1d000-7ffde9c3e000 rw-p ... [stack] 7f8c2a400000-7f8c2ac00000 rw-p ... [stack:tid]

所谓“线程栈在共享映射区”,指的正是这些 mmap 出来的匿名映射区域。


七、为什么 mmap 比 read/write 快?

read/write 至少需要一次“内核缓冲区 → 用户缓冲区”的数据拷贝;
mmap 让用户进程直接访问内核页缓存中的数据,从而避免了这一次拷贝。


先看 read/write 的真实路径

假设你调用:

read(fd, user_buf, size);

实际发生的事情是:

磁盘 ↓ DMA 页缓存(Page Cache) ← 内核态 ↓ memcpy 用户缓冲区 user_buf ← 用户态

关键点来了:

  • 磁盘 → 页缓存

    • 这是 DMA

    • 必须有(磁盘不能直接 DMA 到用户空间)

  • 页缓存 → user_buf

    • 这是一次CPU 拷贝

    • 跨内核态 / 用户态边界

    • 成本高、不可避免(对 read/write)

这一步就是大家说的“用户态 ↔ 内核态拷贝”


mmap 的路径:拷贝去哪了?

现在换成 mmap:

char *p = mmap(...); char x = p[0];

实际路径是:

磁盘 ↓ DMA 页缓存(Page Cache) ↑ 用户进程直接访问(VA → 同一物理页)

关键差异

  • 没有 memcpy

  • 用户虚拟地址直接映射到页缓存中的物理页

  • CPU 只是做一次普通的内存 load/store

页缓存既是“内核缓冲区”,也是“用户可见内存”


所以 mmap 到底“避免”了哪一次拷贝?

我们精确地说:

阶段read/writemmap
磁盘 → 内核页缓存必须必须
内核 → 用户memcpy无拷贝
用户访问普通内存普通内存

mmap避免的是

页缓存 → 用户缓冲区 的那次数据复制


为什么这次拷贝“特别贵”?

CPU 成本高

  • memcpy 是:

    • 逐字节 / cache line 拷贝

    • 占用 CPU

  • 大文件 → 明显拖慢程序


Cache 污染

  • read/write:

    • 数据被复制到 user_buf

    • cache 中出现两份相同数据

  • mmap:

    • 只有一份物理页


NUMA / 大内存下更明显

  • 大页拷贝跨 NUMA 节点

  • mmap 直接访问本地页缓存


八、从内核视角看 mmap(一句话)

mmap 的作用,是在进程页表中记录一条规则:
“当访问这段虚拟地址时,应当如何处理该访问。”

  • 从文件读?

  • 分配匿名页?

  • 是否共享?

  • 是否写时复制?


九、常见误区澄清

❌ mmap = 分配物理内存
✅ mmap = 建立虚拟地址映射

❌ mmap 只能映射文件
✅ 匿名内存是最常见用途之一

❌ 线程栈是特殊区域
✅ 在线程实现中,它只是 mmap 出来的一块内存


十、总结

mmap 是 Linux 虚拟内存机制的核心接口。
它不仅支撑了文件映射、高性能 I/O,也支撑了线程栈、动态内存分配和共享内存。

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

27、Linux 系统打印与程序编译全攻略

Linux 系统打印与程序编译全攻略 在 Linux 系统中,打印和程序编译是两项重要的操作。下面将详细介绍如何在 Linux 系统中进行打印操作以及如何编译程序。 打印操作 在类 Unix 系统中,CUPS 打印套件支持两种历史上常用的打印方法,分别使用 lpr 和 lp 程序。 1. 使用 …

作者头像 李华
网站建设 2026/6/17 18:04:26

35、流量控制与字符串数字处理:for 循环及参数扩展详解

流量控制与字符串数字处理:for 循环及参数扩展详解 1. for 循环 在编程中,for 循环是一种强大的工具,用于处理序列。在现代版本的 bash 中,for 循环有两种形式。 1.1 传统 shell 形式 传统的 for 命令语法如下: for variable [in words]; docommands done其中, va…

作者头像 李华
网站建设 2026/6/17 9:51:14

21、正则表达式入门与元字符详解

正则表达式入门与元字符详解 1. 哈希表遍历 1.1 按预定义顺序遍历哈希表 若要按键插入哈希表的顺序遍历键,需维护一个单独的数组来存储这些键。每次向哈希表添加键时,也要将该键添加到数组中。示例代码如下: my @keys_in_order; my %hash; $hash{thing} = 1; push @key…

作者头像 李华
网站建设 2026/6/17 3:46:27

AutoGPT如何生成Word文档?python-docx调用指南

AutoGPT如何生成Word文档&#xff1f;python-docx调用指南 在当今AI驱动的自动化浪潮中&#xff0c;一个真正“能思考、会动手”的智能体已不再是科幻设想。设想这样一个场景&#xff1a;你只需告诉AI——“帮我写一份关于Python学习计划的报告”&#xff0c;几秒钟后&#xff…

作者头像 李华
网站建设 2026/6/19 12:42:03

鸿蒙PC UI控件库 - TextArea 多行文本输入详解

演示视频地址&#xff1a; https://www.bilibili.com/video/BV1jomdBBE4H/ &#x1f4cb; 目录 概述特性快速开始API 参考使用示例主题配置最佳实践常见问题总结 概述 TextArea 是控件库中的多行文本输入组件&#xff0c;支持字数统计、自动调整高度、验证等功能&#xff…

作者头像 李华
网站建设 2026/6/18 6:11:52

ES6新增的新特性以及用法

目录一、ES6介绍1.1 Let变量定义1.2 箭头函数1.2.1 基本语法1.2.2 this 绑定&#xff08;重要区别&#xff01;&#xff09;1.3 模板字符串1.4 解构赋值1.4.1 数组解构1.4.2 对象解构1.5 扩展运算符1.5.1 数组扩展1.5.2 对象扩展1.6 默认参数1.7 剩余参数1.8 Symbol 类型1.10 S…

作者头像 李华