You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux中struct buffer_head标记为脏后如何被刷写到磁盘?

Linux buffer_head 脏状态刷写磁盘机制

你找不到单独遍历脏buffer_head的后台例程是正常的:2.6版本之后内核就废弃了独立的缓冲区缓存,所有buffer_head都是页缓存(page cache)中内存页的块级描述符,刷写逻辑归属writeback(回写)子系统,不会单独扫描buffer_head做脏状态检查。

核心后台刷写线程

你推测的周期性检查逻辑确实存在,现在的实现是每个块设备独立的flush-<major>:<minor>内核线程,由两类触发源唤醒:

  • 周期性唤醒:全局工作队列上的wb_workfn任务会按照dirty_writeback_centisecs内核参数配置的周期(默认500,即5秒)运行,检查所有块设备回写队列的脏页
  • 事件触发:包括系统可用内存低于水位线、脏页占内存比例超过dirty_background_ratio阈值、用户态调用sync/fsync/fdatasync等显式刷盘接口、文件系统主动触发刷写等场景。

历史版本说明:2.4及更早内核确实存在bdflush后台线程专门扫描脏缓冲区,2.6早期替换为全局pdflush线程,后续为了避免块设备锁竞争又改成了现在的per-block-device flush线程架构,老资料里提到的bdflush/pdflush在5.x及以上版本内核中已经完全移除。

完整刷写链路

当buffer_head被标记为脏(置BH_Dirty位)时,它所属的内存页(高版本内核为folio)也会同步被标记为脏,挂入所属inode的脏页链表、对应块设备的回写队列,后续刷写流程如下:

  1. 回写线程被唤醒后,首先从队列中筛选出脏时长超过dirty_expire_centisecs(默认30秒)的脏页,构造回写批次
  2. 针对每一个脏页,调用对应文件系统注册的address_space_operations->writepages回调,该回调会遍历页的private指针挂载的buffer_head链表,筛选出所有置了BH_Dirty标记的块
  3. 文件系统层为这些脏块构造bioIO请求,同时清除对应buffer_head的BH_Dirty标记,置BH_Lock、BH_WriteReq标记,将bio提交给块层IO调度器
  4. 块层调度器对IO按物理扇区地址排序、合并后,下发给块设备驱动
  5. 磁盘硬件完成写入后触发中断,内核在IO完成回调中清除buffer_head的BH_Lock标记,唤醒所有等待该块写入完成的进程,单次刷写流程结束。

代码定位参考

核心逻辑集中在三个内核源文件中,顺着入口就能捋完完整流程:

  • 回写框架核心逻辑:mm/page-writeback.c、mm/backing-dev.c
  • buffer_head相关的刷写辅助逻辑:fs/buffer.c

内容的提问来源于stack exchange,提问作者shengjiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:27:28