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

如何复现未刷新内核缓冲区导致的数据丢失问题?

如何复现Linux下USB写入未刷入硬件的问题

复现前的准备

  • 准备一个普通USB驱动器,挂载到比如/mnt/usb,先用mount命令确认挂载参数包含async(默认就是该参数,若显示sync则需重新挂载,否则无法复现)
  • 生成一个100MB的测试文件:执行dd if=/dev/urandom of=test_data bs=1M count=100,小文件会被内核快速刷入硬件,难以复现缓冲区滞留问题

复现步骤

  1. 编写模拟导出的测试脚本(替代你的Excel导出逻辑),示例用Python实现:
import os

def fake_export():
    usb_file = "/mnt/usb/test_excel.xlsx"
    # 写入大体积内容,让内核缓冲区积压待写入数据
    with open(usb_file, "wb") as f:
        f.write(os.urandom(1024*1024*100))
        # 仅刷新用户空间缓冲区,不同步内核到硬件
        f.flush()
    print("导出成功(仅刷用户缓冲区)")

if __name__ == "__main__":
    fake_export()
  1. 运行脚本,看到导出成功(仅刷用户缓冲区)的瞬间立刻物理拔除USB驱动器(不要用umount或udisksctl等命令卸载,这类命令会自动触发内核同步,无法复现问题)
  2. 重新挂载USB驱动器,查看/mnt/usb/test_excel.xlsx:要么文件不存在,要么文件大小远小于100MB,或内容损坏,即复现目标问题

为什么之前的方法未成功?

  • 使用命令断开USB:卸载类命令会强制内核将缓冲区数据刷入硬件,相当于自动执行了fsync,无法复现缓冲区滞留场景
  • 手动拔取时机错误:小文件写入后内核会快速自动刷盘(内核有定期同步机制),只有大文件才能让缓冲区积压足够数据,提升复现概率
  • 挂载时使用sync选项:该选项会让所有写入直接同步到硬件,无缓存环节,自然不会出现缓冲区滞留问题

验证fsync的修复效果

修改测试脚本,添加os.fsync强制同步内核缓冲区到硬件:

import os

def fake_export_with_fsync():
    usb_file = "/mnt/usb/test_excel.xlsx"
    with open(usb_file, "wb") as f:
        f.write(os.urandom(1024*1024*100))
        f.flush()
        os.fsync(f.fileno())  # 强制将内核缓冲区数据刷入硬件
    print("导出成功(已刷入硬件)")

if __name__ == "__main__":
    fake_export_with_fsync()

运行后立刻拔取USB,重新挂载后文件应完整存在,说明fsync生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:07:15