最近遇到文件损坏(0 Byte)的问题,原因是fopen及fwrite操作后,缓存中的文件还未真正写到硬盘中,系统就被重启,导致文件fd损坏(0 Byte)。 为了解决此问题,需要在 fopen 及 fwrite之后,调用fsync,确保缓存中的数据刷新到硬盘上后返回,然后再fclose,避免文件损坏。 也可以再fopen中指定O_SYNC解决此问题。 当然使用上述方法的代价是写入性能的大幅低下,可通过增大BUFF size改善。 == 分享一篇关于此类Trouble的详细文章:
先看一个open函数的使用例子.

 O_DIRECT: 无缓冲的输入、输出。 O_SYNC:以同步IO方式打开文件。 下面对这两个flag做一些详细的说明。 一,O_DIRECT,绕过缓冲区高速缓存,直接IO 直接IO:Linux允许应用程序在执行磁盘IO时绕过缓冲区高速缓存,从用户空间直接将数据传递到文件或磁盘设备,称为直接IO(direct IO)或者裸IO(raw IO)。 应用场景:数据库系统,其高速缓存和IO优化机制均自成一体,无需内核消耗CPU时间和内存去完成相同的任务。 使用直接IO的弊端:可能会大大降低性能,内核对缓冲区告诉缓存做了不少优化,包括:按顺序预读取,在成簇磁盘块上执行IO,允许访问同一文件的多个进程共享高速缓存的缓冲区。 使用方法:在调用open函数打开文件或设备时指定O_DIRECT标志。 注意可能发生的不一致性:若一进程以O_DIRECT标志打开某文件,而另一进程以普通(即使用了高速缓存缓冲区)打开同一文件,则由直接IO所读写的数据与缓冲区高速缓存中内容之间不存在一致性,应尽量避免这一场景。 使用直接IO需要遵守的一些限制:
不遵守上述任一限制均将导致EINVAL错误。 二,O_SYNC,以同步方式写入文件 功能:强制刷新内核缓冲区到输出文件。这是有必要的,因为为了数据安全,需要确保将数据真正写入磁盘或者磁盘的硬件告诉缓存中。 我们先熟悉一下同步IO相关定义和系统调用。 同步IO数据完整性和同步IO文件完整性同步IO的定义:某一IO操作,要么已成功完成到磁盘的数据传递,要么被诊断为不成功。SUSv3定义的两种同步IO完成类型(此处用英文,因为译者也忍无可忍用了原文…)
1 fsync 作用:fsync()系统调用将使缓冲数据和fd相关的所有元数据都刷新到磁盘上。调用fsync会强制使文件处于Synchronized IO file integrity completion状态。 函数声明:

函数返回值:
2 fdatasync 作用:fdatasync()系统调用的作用类似fsync(),只是强制文件处于synchronized IO data integrity compeletion状态。 函数声明:

函数返回值:
3 sync系统调用 作用:sync()系统调用会使包含更新文件信息的所有内核缓冲区(即数据块、指针块、元数据等)刷新到磁盘上。 函数声明:

细节:若内容发生变化的内核缓冲区在30s内未经显式方式同步到磁盘上,则一条长期运行的内核线程会确保将其刷新到磁盘上。这一做法是为了规避缓冲区与相关磁盘文件内容长期处于不一致状态。 4 使所有写入同步:O_SYNC 调用open()函数时,如制定O_SYNC标志,则会使所有后续输出同步。
作用:调用open后,每个write调用会自动将文件数据和元数据刷新到磁盘上,即按照Synchronized IO file integrity completion的要求执行写操作。 5 有无O_SYNC性能对比 场景:将一百万字节写入一个ext2文件系统上的新创建文件,比较写入时间。 对比结果: 从结果中可以得到的结论:
三,IO缓冲层次关系先总结一下stdio函数库和内核采用的缓冲这两级缓冲,然后用图说明两层缓冲机制和各种缓冲类型的控制机制。
上图中,左侧虚线方框中为可于任何时刻显式强制刷新各类缓冲区的调用。 右侧所示为促使刷新自动化的调用:通过禁用stdio的缓冲,和在文件输出类的系统调用中启用同步,从而使每个write()调用立刻刷新到磁盘。 四,小结输入输出数据的缓冲由内核和stdio库完成。有时可能希望阻止缓冲,但这需要了解其对应用程序性能的影响。 可以使用各种系统调用和库函数来控制内核和stdio缓冲,并执行一次性的缓冲区刷新。 在Linux环境下,open()所特有的O_DIRECT标识允许特定应用跳过缓冲区高速缓存。 原帖:https://blog.csdn.net/AXW2013/article/details/70242228 |
[技术| 编程·课件·Linux] Trouble Shooting:文件损坏(0 Byte)及 fsync 或者(f ...
admin
· 发布于 2019-11-19 14:47
· 1608 次阅读
转载文章时务必注明原作者及原始链接,并注明「发表于 软院网 RuanYuan.Net 」,并不得对作品进行修改。
暂无回复。