刷盘flush vs fsync:操作系统 IO 数据流
·
任何涉及磁盘读写的应用(MySQL、Kafka、ES、Redis AOF 等),底层都离不开这套 IO 机制。这是一篇通用型的操作系统 IO 笔记。
概念:刷盘的两步
"刷盘"这个词在日常使用中比较模糊,在 OS 层面实际分两个步骤:
完整数据流转路径
数据从应用写入磁盘、从磁盘发送到网络的完整路径,涉及用户态 ↔ 内核态切换、DMA 拷贝等概念。以下三张图分别展示三种场景。
① 写路径(write 方向)
数据从用户进程 → 内核 Page Cache → 磁盘。
用户态 内核态 硬件
┌──────────┐ write ┌─────────────┐ fsync ┌──────┐
│ 用户缓冲区 │──────► │ Page Cache │ ────► │ 磁盘 │
│ (stdio) │ flush │ (内核缓冲区) │ │ │
└──────────┘ └─────────────┘ └──────┘
-
•
write()/flush():用户态 → 内核态(数据到达 Page Cache,未落盘) -
•
fsync():Page Cache → 磁盘(真正落盘,持久化)
② 读 + 发送路径(sendfile / 零拷贝)
数据从磁盘 → 内核 Page Cache → 直接到网卡,不经过用户态,减少拷贝次数。
硬件 内核态 硬件
┌──────┐ DMA ┌───────────┐ DMA ┌──────┐
│ 磁盘 │ ───►│ PageCache │ ───►│ 网卡 │
└──────┘ │(内核缓冲区) │ └──────┘
└───────────┘
▲
sendfile()(不经过用户态)
┌──────┴─────┐
│ 用户进程 │ ←只发命令,无数据
└────────────┘
-
• 只产生 2 次 DMA 拷贝(磁盘→Page Cache,Page Cache→网卡)
-
• 用户进程仅发起
sendfile()系统调用,不参与数据搬运
③ 传统 read + write 路径(4 次拷贝)
数据从磁盘 → 内核 → 用户态 → 内核 → 网卡,经历 4 次拷贝,CPU 参与其中 2 次。
硬件 内核态 用户态 内核态 硬件
┌──────┐ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐
│ 磁盘 │──►│PageCache│──►│用户缓冲区 │──►│SocketBuf │──►│ 网卡 │
└──────┘ └─────────┘ └──────────┘ └──────────┘ └──────┘
DMA ① DMA ② CPU ③ CPU ④ DMA

对比上图:sendfile 省去了 ②和③ 两次 CPU 拷贝,且无需切换用户态/内核态,因此称为"零拷贝"。
flush vs fsync 对比

一句话总结:flush 是 C 库 → 内核,fsync 是内核 → 磁盘。只有 fsync 才算真正落盘。
场景速查:各产品 IO 策略对比

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)