news 2026/4/2 7:26:27

页缓存技术(PageCache/sendfile/mmap)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
页缓存技术(PageCache/sendfile/mmap)

核心概念解析

1.PageCache(页缓存)

  • 是什么
    Linux 内核将磁盘文件数据缓存在物理内存中的一块区域,称为 PageCache。
  • 作用
    • 读操作:若数据在 PageCache 中,直接返回,避免磁盘 I/O
    • 写操作:先写入 PageCache,由内核异步刷盘(write-back),提升写性能。
  • 特点
    • 对所有进程透明共享;
    • LRU 策略淘汰冷数据;
    • 是“零拷贝”技术的基础。

2.mmap(Memory-Mapped File)

  • 是什么
    将一个文件直接映射到用户进程的虚拟地址空间,程序可像操作数组一样读写文件。
  • 系统调用
    void*addr=mmap(NULL,length,PROT_WRITE,MAP_SHARED,fd,0);
  • 工作原理
    • 不立即加载文件内容;
    • 当程序访问addr[i]时,触发缺页中断(Page Fault)
    • 内核分配物理页,从磁盘(或 PageCache)加载数据;
    • 后续读写直接操作内存,无需read()/write()系统调用
  • 优点
    • 减少系统调用和上下文切换;
    • 适合大文件随机访问或高频小写。

注意:mmap 本身不等于零拷贝,但它为高效 I/O 提供了基础。

3.sendfile(零拷贝网络传输)

  • 是什么
    Linux 提供的系统调用,允许直接从文件描述符传输数据到 Socket,全程由内核完成。
  • 系统调用
    ssize_tsendfile(intout_fd,intin_fd,off_t*offset,size_tcount);
  • 工作原理(Linux 2.4+)
    • 数据路径:磁盘 → PageCache → 网卡
    • CPU 不参与数据拷贝,仅由 DMA 控制器完成;
    • 内核通过Scatter-Gather DMA直接组装网络包。
  • 前提条件
    • 源必须是文件(支持mmap);
    • 目标必须是 Socket;
    • 数据需在 PageCache 中(否则先加载)。

sendfile 是真正的“零拷贝”(Zero-Copy)。

交互流程图(Mermaid Sequence Diagram)

以下分别绘制传统 I/Ommap 写入sendfile 读取三种场景的数据流,并标注关键组件交互。

DiskKernel (PageCache)NIC (Network)User ProcessDiskKernel (PageCache)NIC (Network)User Process场景1: 传统 read() + write() —— 4次拷贝, 4次上下文切换场景2: mmap 写入文件 —— 1次CPU拷贝, 0次显式系统调用场景3: sendfile 读取并发送 —— 0次CPU拷贝, 零拷贝!1. read(fd, buffer, size)2. DMA: 磁盘 → PageCache3. 数据加载完成4. CPU拷贝: PageCache → 用户buffer5. write(socket, buffer, size)6. CPU拷贝: 用户buffer → Socket缓冲区7. DMA: Socket缓冲区 → 网卡8. 发送完成9. *(mmap_addr + offset) = data10. 缺页中断 (Page Fault)11. (若冷数据) DMA: 磁盘 → PageCache12. 映射物理页到虚拟地址13. 数据已写入 PageCache14. (异步) DMA: PageCache → 磁盘15. sendfile(socket, file_fd, offset, count)16. (若冷数据) DMA: 磁盘 → PageCache17. DMA: PageCache → 网卡 (Scatter-Gather)18. 发送完成

关键对比:拷贝次数与上下文切换

场景CPU 拷贝次数DMA 拷贝次数上下文切换是否零拷贝
传统 I/O2 次2 次4 次
mmap 写入0~1 次*1~2 次0~1 次*❌(但高效)
sendfile 读取0 次2 次2 次

*注:mmap 首次访问触发缺页中断算 1 次上下文切换,后续无开销。

三者如何协同工作?

在高性能服务中,mmap + PageCache + sendfile 可形成完美闭环

  1. 写入阶段
    • 应用通过mmap将数据写入文件 → 数据进入PageCache
  2. 读取阶段
    • 另一请求调用sendfile读该文件 → 内核发现数据已在PageCache
    • 直接通过DMA将 PageCache 数据发往网卡;
  3. 全程
    • 无 CPU 拷贝
    • 无用户态参与
    • 延迟最低、吞吐最高

🌰 典型应用:

  • Web 服务器(如 Nginx)静态文件服务;
  • 消息队列(RocketMQ/Kafka)消息读取;
  • 数据库 WAL 日志传输。

注意事项

  1. PageCache 是共享资源

    • 若系统内存不足,PageCache 被回收 → 性能骤降;
    • 建议为 I/O 密集型服务预留足够内存。
  2. mmap 不等于持久化

    • 数据在 PageCache 中可能因断电丢失;
    • 需调用msync()或依赖 OS 刷盘策略。
  3. sendfile 有局限性

    • 不能修改数据(如加解密、压缩);
    • 若需处理数据,仍需传统 I/O。

总结

  • PageCache:操作系统级缓存,是高性能 I/O 的基石;
  • mmap:让用户态高效写入文件,减少系统调用;
  • sendfile:实现真正的零拷贝网络传输,释放 CPU;

💡三者结合 = 最大化利用硬件(DMA)、最小化 CPU 干预 = 极致 I/O 性能

概括

“mmap 是写入数据,sendfile 是发送数据”
mmap 主要优化写入路径(文件生成),sendfile 优化读取+网络发送路径(文件分发)。

“都使用了 PageCache”
PageCache 是 Linux I/O 性能的“中枢”,无论是read/writemmap还是sendfile,只要操作普通文件,默认都会经过 PageCache(除非用O_DIRECT绕过)。

“mmap 将数据写入 PageCache 后异步刷盘,不等待,体现响应优势”
mmap 的写入本质上是写内存(虚拟地址)→ 触发缺页 → 写 PageCache,应用线程立即返回,刷盘由内核后台完成。这显著降低了写入延迟,特别适合高频小写场景(如日志、消息)。

“sendfile 直接跳过 UserProcess,连接 PageCache 到网络端口,避免拷贝”
传统read + write需要把数据从内核拷到用户态再拷回内核,而 sendfile全程在内核态完成,CPU 不搬运数据,仅靠 DMA 控制器传输,真正实现“零 CPU 拷贝”。

注意事项

  • mmap 本身不保证数据持久化(断电可能丢),需配合msync()或依赖 OS 刷盘策略;
  • sendfile 要求源是文件、目标是 socket,且不能修改数据内容(如加密、压缩),否则仍需传统 I/O。

传统read/writevsmmapvssendfile对比表

维度传统read() + write()mmap()(用于写入)sendfile()(用于读取+发送)
典型用途通用文件读写高频写入/大文件映射文件 → Socket 零拷贝传输
是否经过 PageCache✅ 是✅ 是✅ 是
CPU 数据拷贝次数2 次
(PageCache ↔ 用户 buffer)
0 次
(直接写 PageCache)
0 次
(PageCache → NIC)
DMA 拷贝次数2 次1~2 次2 次
上下文切换次数4 次
(read 进/出 + write 进/出)
0~1 次
(仅首次缺页中断)
2 次
(sendfile 调用进/出)
是否零拷贝❌ 否❌(但高效)✅ 是
写入延迟较高(需等 write 返回)极低(写内存即返回)不适用(只读)
读取+网络吞吐中等不适用(主要用于写)极高(CPU 开销最小)
能否修改数据✅ 可在用户态处理✅ 可直接修改内存❌ 无法干预数据内容
适用场景通用、需处理数据日志写入、消息存储、大文件编辑静态文件服务、消息拉取、视频流

关键结论

  • mmap 的优势在“写”:让写入像操作内存一样快,降低延迟
  • sendfile 的优势在“读+发”:让传输像 DMA 直连一样高效,提升吞吐、降低 CPU
  • 两者都依赖 PageCache:热数据在内存中时性能最佳;
  • 传统 read/write 最灵活但开销最大:适合需要在用户态处理数据的场景(如解密、格式转换)。

高性能系统设计原则

  • 能用 sendfile 就不用 read/write(如静态资源、原始消息转发);
  • 高频写入优先考虑 mmap(如日志、CommitLog);
  • 必须处理数据时,才退回到传统 I/O
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 17:57:06

【课程设计/毕业设计】基于机器学习深度学习算法训练数字识别

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/3/29 1:29:31

计算机深度学习毕设实战-基于 人工智能深度学习算法训练数字识别

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/4/1 19:17:36

华为OD机考双机位C卷 - 任务编排系统 (Java Python JS C/C++ GO )

最新华为上机考试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 华为OD机考双机位C卷 - 任务编排系统 题目描述 任务编排服务负责对任务进行组合调度。参与编排的任务有两种类型,其中一种执行时长为taskA,另一种执…

作者头像 李华
网站建设 2026/3/24 14:23:19

基于人脸识别的企业员工考勤管理系统没视频应用和研究

文章目录人脸识别考勤系统的研究背景系统核心技术非视频应用场景研究进展与挑战实际应用价值项目简介大数据系统开发流程主要运用技术介绍爬虫核心代码展示结论源码文档获取定制开发/同行可拿货,招校园代理 :文章底部获取博主联系方式!人脸识别考勤系统的…

作者头像 李华
网站建设 2026/3/26 4:08:59

AI Agent 记忆系统设计:短期记忆与长期记忆

本质上,目前的LLM只是一个无状态的函数。输入,计算,输出,结束。每一次交互,对它来说都是初见。 要让工具进化为Agent,必须引入状态。这个状态,就是记忆。没有记忆,智能就无法在时间维…

作者头像 李华
网站建设 2026/3/24 6:43:37

Python 之 fuzzywuzzy 进行字符串模糊匹配

fuzzywuzzy 是 Python中 基于 Levenshtein 距离算法的字符串模糊匹配库,提供 fuzz.ratio 、 partial_ratio 、 token_sort_ratio 等核心函数,用于高效计算字符串相似度。该库广泛应用于数据清洗、拼写纠错、文本挖掘和用户输入处理等场景。比如识别相同新…

作者头像 李华