0

0

Linux 写入为何比读取慢?

舞夢輝影

舞夢輝影

发布时间:2026-01-23 19:29:02

|

683人浏览过

|

来源于php中文网

原创

write() 更易卡住因内核写入路径长且可控性低:需经脏页管理、回写调度、设备队列等多层,而 read() 常命中页缓存或仅单次 I/O;脏页批量回写时进程阻塞,iostat 无负载但 vmstat 显示 pgpgout 飙高。

linux 写入为何比读取慢?

为什么 write()read() 更容易卡住

根本原因不在磁盘本身,而在内核的写入路径更长、可控性更低。读取通常能从页缓存直接返回(命中时),而写入必须经过脏页管理、回写调度、设备队列等多层缓冲与决策。

常见现象:write() 突然阻塞数秒,strace 显示卡在系统调用里;iostat 却没看到明显 I/O;vmstat 1pgpgout 飙高但 bi(块输入)几乎为 0——这说明脏页正在被内核批量回写,而非你的进程在直接写盘。

  • write() 默认是“异步提交到页缓存”,不等落盘;但当缓存快满(vm.dirty_ratio 触发)、或调用 fsync()/close() 时,内核会强制同步刷脏页,此时你的线程就会卡住
  • read() 若缓存命中,全程不碰磁盘;即使未命中,也只触发一次预读+单次 I/O,路径短、无累积效应
  • SSD 或 NVMe 上写放大、GC 延迟也会在回写阶段集中暴露,但用户感知为“写比读慢”

O_DIRECT 能绕过缓存加速写入吗

不能一概而论——它绕过了页缓存,但也放弃了内核的预读、合并、延迟调度等优化,实际效果取决于 workload 和硬件。

适用场景:已自行实现高效缓存/预取逻辑(如数据库)、写入流高度顺序且大小对齐(如 4K 对齐的大块日志)。

GNU make 中文手册 pdf版
GNU make 中文手册 pdf版

GNU makefile中文手册 pdf,文比较完整的讲述GNU make工具,涵盖GNU make的用法、语法。同时重点讨论如何为一个工程编写Makefile。阅读本书之前,读者应该对GNU的工具链和Linux的一些常用编程工具有一定的了解。诸如:gcc、as、ar、ld、yacc等本文比较完整的讲述GNU make工具,涵盖GNU make的用法、语法。重点讨论如何使用make来管理软件工程、以及如何为工程编写正确的Makefile。 本手册不是一个纯粹的语言翻译版本,其中对GNU make的一些语法

下载
  • 必须确保用户缓冲区地址和长度都按存储设备逻辑块大小对齐(通常是 512B 或 4K),否则 write() 直接返回 -EINVAL
  • 每次 write() 都真实下发 I/O 请求,无法合并;小块随机写 + O_DIRECT 会让 IOPS 爆表、延迟飙升
  • O_DIRECT 不保证元数据(如文件大小更新)落盘,fsync(O_SYNC) 仍需额外调用

哪些配置项真正影响写入延迟

关键不是调大缓存,而是控制脏页生成节奏和回写时机。默认值适合吞吐优先场景,对低延迟写入反而有害。

  • vm.dirty_ratio(默认 80):触发同步回写的脏页百分比上限;建议降至 30–50,避免突发刷盘阻塞
  • vm.dirty_background_ratio(默认 10):后台线程开始异步回写的阈值;建议设为 5–15,让刷盘更平滑
  • vm.dirty_expire_centisecs(默认 3000 = 30 秒):脏页最大驻留时间;若应用要求强一致性,可压到 500(5 秒)以内
  • /proc/sys/vm/swappiness 设为 0 可减少因内存压力导致的意外换出干扰写入路径

如何快速验证是否是内核回写导致的写延迟

不用上 perf 或 ftrace,几个简单命令就能定位:

  • 运行 watch -n 1 'cat /proc/meminfo | grep -E "Dirty|Writeback"':观察 Dirty 值是否周期性冲高后骤降(典型回写行为)
  • 执行 echo 1 > /proc/sys/vm/drop_caches 后再测写入——如果延迟大幅下降,说明原先是脏页积压所致(注意:这仅用于诊断,勿在生产环境乱用)
  • perf record -e 'syscalls:sys_enter_write' -a sleep 10 抓取写系统调用耗时分布,再 perf script 查看是否有大量 >100ms 的样本

真正难处理的是混合负载:一边有日志持续写入,一边有备份进程 dd if=/dev/sda of=/backup.img 扫盘——后者会污染页缓存并触发全局回写,导致前者写入抖动。这种干扰很难靠单个参数消除。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

765

2023.08.22

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

354

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2076

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

348

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

324

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

411

2023.10.16

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.6万人学习

Git 教程
Git 教程

共21课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号