gpt4 book ai didi

c - fflush、fsync 和 sync 与内存层

转载 作者:IT王子 更新时间:2023-10-29 00:15:18 57 4
gpt4 key购买 nike

我知道已经有类似的问题了,我看了看,但找不到明确、明确的答案来回答我的问题。我只是在网上调查这些功能及其与内存层的关系。特别是我发现这个美丽的 article这让我对内存层有了很好的了解

memory layers

似乎 fflush() 将数据从应用程序移动到内核文件系统缓冲区,没关系,每个人似乎都同意这一点。唯一让我感到困惑的是,在同一篇文章中,他们假设一个写回缓存说 fsync() “数据被保存到稳定的存储层”,然后他们添加了“存储本身可能将数据存储在回写缓存中,因此使用 O_DIRECT 打开的文件仍然需要 fsync() 以便将数据保存到稳定的存储中”

阅读 herethere看起来事实是 fsync()sync() 让数据进入存储设备,但如果这个有缓存层,它只是移动到这里,而不是在一旦发生永久性存储,如果出现电源故障,数据甚至可能丢失。除非我们有一个启用了屏障的文件系统,然后 "sync()/fsync() 和一些其他操作将导致适当的 CACHE FLUSH (ATA) 或 SYNCHRONIZE CACHE (SCSI ) 要发送到设备的命令” [来自您的网站 answer ]

问题:

  1. 如果要更新的数据已经在内核缓冲区中,并且我的设备在回写模式下有一个 volatile 缓存层,是否真的如文章所述,fsync() 之类的操作 [和 sync() 我想] 将数据同步到稳定内存层,跳过 volatile 内存层?我认为这是直写式缓存发生的情况,而不是回写式缓存。从我读到的内容我了解到,通过 fsync() 上的回写缓存可以将数据发送到将它们放入 volatile 缓存中的设备,并且它们只会在之后进入永久内存

  2. 我读到 fsync() 使用文件描述符,然后使用单个文件,而 sync() 导致缓冲区的整体部署,因此它适用于每一个要更新的数据。从这个page fsync() 等待写入磁盘结束,而 sync() 不等待实际写入磁盘结束。两者之间的内存数据传输是否存在其他差异?

感谢那些愿意提供帮助的人

最佳答案

1. 正如您从研究中正确得出的结论,fflush用户空间缓冲 数据同步到内核级别 缓存(因为它使用驻留在用户级别且对内核不可见的 FILE 对象),而 fsyncsync (工作直接使用文件描述符)将内核缓存数据与设备同步。然而,后者并不能保证数据已实际写入存储设备——因为这些通常也带有自己的缓存。我希望使用 MS_SYNC 标志调用的 msync 也是如此。

与此相关,我发现 synchronizedsynchronous 操作之间的区别在讨论该主题时非常有用。方法如下 Robert Love简明扼要地说:

A synchronous write operation does not return until the written data is—at least—stored in the kernel’s buffer cache. [...] A synchronized operation is more restrictive and safer than a merely synchronous operation. A synchronized write operation flushes the data to disk, ensuring that the on-disk data is always synchronized vis-à-vis the corresponding kernel buffers.

考虑到这一点,您可以使用 O_SYNC 标志(连同其他一些以写入权限打开文件的标志)来调用 open 以强制执行同步写入操作。同样,正如您正确假设的那样,这仅适用于 WRITE THROUGH 磁盘缓存策略,这实际上相当于禁用磁盘缓存。

您可以阅读 this answer关于如何在 Linux 上禁用磁盘缓存。请务必同时检查 this website除了基于 ATA 的设备外,它还涵盖基于 SCSI 的设备(要了解不同类型的磁盘,请参阅此 page on Microsoft SQL Server 2005,最后更新:2018 年 4 月 19 日)。

说到这里,在 Windows machines 上阅读有关如何处理该问题的信息非常有用。 :

To open a file for unbuffered I/O, call the CreateFile function with the FILE_FLAG_NO_BUFFERING and FILE_FLAG_WRITE_THROUGH flags. This prevents the file contents from being cached and flushes the metadata to disk with each write. For more information, see CreateFile.

显然,这就是Microsoft SQL Server 2005家庭确保数据完整性:

All versions of SQL Server open the log and data files using the Win32 CreateFile function. The dwFlagsAndAttributes member includes the FILE_FLAG_WRITE_THROUGH option when opened by SQL Server. [...]This option instructs the system to write through any intermediate cache and go directly to disk. The system can still cache write operations, but cannot lazily flush them.

我说这特别有用,因为这个 blog post from 2012显示某些 SATA 磁盘忽略 FILE_FLAG_WRITE_THROUGH!我不知道目前的情况如何,但似乎为了确保写入磁盘是真正同步的,你需要:

  1. 使用您的设备驱动程序禁用磁盘缓存。
  2. 确保您使用的特定设备支持直写/无缓存策略。

但是,如果您正在寻找数据完整性的保证,您可以只购买一个磁盘,它有自己的电池供电,而不是电容器(通常只够完成正在进行的写入过程)。正如上面提到的博客文章中的结论:

Bottom-line, use Enterprise-Class disks for your data and transaction log files. [...] Actually, the situation is not as dramatic as it seems. Many RAID controllers have battery-backed cache and do not need to honor the write-through requirement.

2.要(部分)回答第二个问题,这是来自手册页SYNC(2):

According to the standard specification (e.g., POSIX.1-2001), sync() schedules the writes, but may return before the actual writing is done. However, since version 1.3.20 Linux does actually wait. (This still does not guarantee data integrity: modern disks have large caches.)

这意味着 fsyncsync 的工作方式不同,但是请注意,它们都是在 unistd.h 中实现的,这表明存在一定的一致性它们之间。但是,我会关注 Robert Love谁不建议在编写自己的代码时使用 sync 系统调用。

The only real use for sync() is in the implementation of the sync utility. Applications should use fsync() and fdatasync() to commit to disk the data of only the requisite file descriptors. Note that sync() may take several minutes or longer to complete on a busy system.

关于c - fflush、fsync 和 sync 与内存层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30186526/

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com