Ant*_*ino 10 c linux caching sync fsync
我知道已经有类似的问题,我给了他们一个看,但我找不到一个明确的单一答案我的问题.我只是在网上调查这些函数及其与内存层的关系.特别是我发现这篇精美的文章让我对内存层有了很好的了解

似乎fflush()将数据从应用程序移动到内核文件系统缓冲区并且没关系,每个人似乎都同意这一点.令我困惑的唯一一件事就是在同一篇文章中他们假设一个回写缓存,说fsync()"数据被保存到稳定的存储层",并且在他们添加"存储本身可以将数据存储在写入中"之后-back cache,因此fsync()仍然需要使用O_DIRECT打开的文件,以便将数据保存到稳定存储"
在这里和那里阅读似乎事实就是这样fsync(),sync()让数据进入存储设备,但如果这个数据有缓存层,它只是移动到这里,而不是立即存储到永久存储,如果出现电源故障,数据甚至可能会丢失.除非我们有一个启用了障碍的文件系统,然后" sync()/ fsync()和其他一些操作将导致相应的CACHE FLUSH(ATA)或SYNCHRONIZE CACHE(SCSI)命令被发送到设备"[来自您的网站答案 ]
问题:
如果要更新的数据已经在内核缓冲区中并且我的设备在回写模式下有一个易失性缓存层,那么就像文章所说的那样,像fsync()[和sync()我想的那样]操作将数据同步到稳定的内存层跳过易变的?我认为这是通过直写缓存而不是回写缓存所发生的情况.从我读到的内容中我了解到,使用回写式缓存fsync()可以将数据发送到设备,将数据放入易失性缓存中,只有在之后才能进入永久性内存
我读过它fsync()使用文件描述符,然后使用单个文件,同时sync()导致缓冲区的完全部署,因此它适用于每个要更新的数据.并且从该页面还fsync()等待写入磁盘sync()的结束,而不等待实际写入磁盘的结束.两者之间的内存数据传输是否存在其他差异?
感谢那些愿意帮助的人
1.正如您从研究中得出的正确结论,将用户空间缓冲fflush数据同步到内核级缓存(因为它正在处理驻留在用户级且对内核不可见的对象),而或(直接使用文件描述符)将内核缓存的数据与设备同步。但是,后者不能保证数据已实际写入存储设备 \xe2\x80\x94,因为这些设备通常也带有自己的缓存。我预计对于带有标志的跟注也同样适用。FILEfsyncsyncmsyncMS_SYNC
相关地,我发现在讨论该主题时同步和同步操作之间的区别非常有用。罗伯特·洛夫 (Robert Love)的简洁表述如下:
\n\n\n同步写操作只有在写入的数据\xe2\x80\x94至少\xe2\x80\x94存储在内核\xe2\x80\x99s缓冲区缓存中时才会返回。[...] 同步操作比单纯的同步操作更具限制性且更安全。同步写入操作将数据刷新到磁盘,确保磁盘上的数据始终与相应的内核缓冲区同步。
\n
考虑到这一点,您可以open使用O_SYNCflag 进行调用(与其他一些以写入权限打开文件的标志一起)来强制执行同步写入操作。同样,正如您正确假设的那样,这仅适用于WRITE THROUGH磁盘缓存策略,这实际上相当于禁用磁盘缓存。
您可以阅读有关如何在 Linux 上禁用磁盘缓存的答案。请务必查看此网站,该网站还涵盖基于 SCSI 和基于 ATA 的设备(要了解不同类型的磁盘,请参阅Microsoft SQL Server 2005 上的此页面,最后更新时间:2018 年 4 月 19 日)。
\n说到这里,阅读有关如何在Windows 计算机上处理该问题的信息非常有用:
\n\n\n要打开无缓冲 I/O 的文件,请使用 FILE_FLAG_NO_BUFFERING 和 FILE_FLAG_WRITE_THROUGH 标志调用 CreateFile 函数。这可以防止文件内容被缓存并在每次写入时将元数据刷新到磁盘。有关详细信息,请参阅创建文件。
\n
显然,这就是Microsoft SQL Server 2005系列确保数据完整性的方式:
\n\n\n所有版本的 SQL Server 使用 Win32 CreateFile 函数打开日志和数据文件。当 SQL Server 打开时,dwFlagsAndAttributes 成员包括 FILE_FLAG_WRITE_THROUGH 选项。[...]\n此选项指示系统通过任何中间缓存写入并直接写入磁盘。系统仍然可以缓存写操作,但不能延迟刷新它们。
\n
我之所以说这是信息丰富的,是因为2012 年的这篇博文显示某些 SATA 磁盘忽略了FILE_FLAG_WRITE_THROUGH! 我不知道目前的情况是什么,但似乎为了确保写入磁盘真正同步,您需要:
但是,如果您正在寻求数据完整性的保证,您可以购买带有自己的基于电池的电源的磁盘,该电源超出了电容器(通常仅足以完成正在进行的写入过程)。正如上述博客文章的结论所示:
\n\n\n最重要的是,使用企业级磁盘来存储数据和事务日志文件。[...] 事实上,情况并没有看起来那么戏剧化。许多 RAID 控制器都有电池支持的缓存,不需要满足直写要求。
\n
2.(部分)回答第二个问题,这是来自手册页SYNC(2):
\n\n根据标准规范(例如,POSIX.1-2001),sync() 会调度写入,但可能会在实际写入完成之前返回。然而,从 1.3.20 版本开始,Linux 实际上会等待。(这仍然不能保证数据完整性:现代磁盘具有大量缓存。)
\n
这意味着fsync和sync工作方式不同,但是,请注意,它们都是在其中实现的,unistd.h这表明它们之间存在一定的一致性。然而,我会跟随罗伯特·洛夫(Robert Love),他不建议使用sync在编写自己的代码时使用系统调用。
\n\nsync() 的唯一真正用途是同步实用程序的实现。应用程序应使用 fsync() 和 fdatasync() 仅将必需的文件描述符的数据提交到磁盘。请注意,在繁忙的系统上,sync() 可能需要几分钟或更长时间才能完成。
\n