Linux 上“blockdev --flushbufs”和“sync”之间的区别?

Linux 上“blockdev --flushbufs”和“sync”之间的区别?

跑步和练习有什么区别吗blockdev --flushbufs在实践中运行和sync(1)在 Linux 上(除了blockdev针对特定设备的冲洗以及sync系统范围内的冲洗)。

sync(1)联机帮助页说它会刷新文件系统缓冲区(仅?)。如果dd在不经过文件系统层的情况下对驱动器(例如)进行 I/O ,sync真的是无效的吗?

我什么时候应该使用其中一种而不是另一种?

答案1

如果在不经过文件系统层的情况下对驱动器(例如 dd)进行 I/O,那么同步真的效率低下吗?

这就引出了一个问题:写入设备节点绕过“文件系统层”。我想从某种意义上说它显然是...

无论如何,都没有关系。如果您所做的事情不涉及缓存,那么sync无论如何运行(或类似的操作)都不会“效率低下”:如果没有任何内容需要同步,那么这就是一个微不足道的调用。

什么时候应该使用其中一种而不是另一种?

我想当你想针对特定分区时,blockdev这是有意义的。我看不出它比sync其他方式有什么特别的优势(反之亦然)。

答案2

blockdev --flushbufs如果由底层驱动程序/硬件实现,将刷新设备本身的写入缓冲区。在企业硬件块设备中,除非有电池支持,否则通常不会保留脏写缓冲区,在移动硬件或更换电池之前仍然需要刷新它们(这通常在关闭过程结束时自动完成,就在执行 ACPI 关闭或重置之前)。

大多数企业和高端桌面机械驱动器都有一个读/写缓存,可以配置为执行或不执行写缓存,这就是将使用此 ioctl 刷新的缓存。确保在拔出 USB 或 eSATA 连接的块设备之前刷新所有数据可能很有用,即使在执行同步之后也是如此。

此 ioctl 并不总是可靠,某些驱动程序或设备可能缺少实现或拦截调用。 IIRC 甚至旧版本的 LVM 在逻辑卷上使用时也会拦截此 ioctl,并且无法刷新物理设备。

sync()/syncfs()/fsync()/fdatasync()有不同的目的,他们会将所有未写入的数据/元数据同步回设备。该数据可能包括脏mmap()页、VFS 层中的脏缓冲区以及未提交的文件系统更改。fdadasync()仅刷新特定文件的数据,因此这是确保刷新数据更改的最有效方法(除非需要,否则它仍然可能会延迟某些元数据更新,例如文件大小更改)。所有其他sync()调用将刷新文件、文件系统或所有文件系统上的所有内容。如果数据被认为很重要,那么同步数据应该是程序的工作,如果您必须诉诸完整的同步调用来确保所有内容都正确写入,那么效率显然要低得多(程序sync还可以同步特定的文件系统或文件的数据,看man sync)。

如果目标是删除设备并且您可以卸载它,则甚至不需要同步;卸载文件系统将已经刷新操作系统级别的所有缓冲区(blockdev --flushbufs如果存在较大的写入缓存并且您在之后立即断开设备连接,则可能仍然需要)。如果系统处于不良状态并且您无法卸载,那么同步可能是您在重新启动之前可以做的下一个最好的事情(尝试先杀死所有可能写入它的应用程序)。

此外,尽管块设备上的写入缓存很容易导致数据丢失,但大多数现代日志文件系统都能很好地应对它,甚至无需在fsck电源故障后运行(文件系统的日志将拥有将元数据纠正为已知良好状态)。 OTOH 对于文件系统上的文件数据来说通常情况并非如此,如果设计不当的应用程序没有正确刷新,您最终可能会得到损坏的文件。

相关内容