cp
在Linux中,诸如或等命令的执行完成dd
并不意味着数据已写入设备。例如,一个人必须打电话sync
,或调用驱动器上的“安全删除”或“弹出”功能。
这种方法背后的理念是什么?为什么不一次性写入数据?写入是否会因 I/O 错误而失败?
答案1
它只是给程序带来了速度的错觉,而实际上不必等到写入完成。以同步模式挂载您的文件系统(这使您可以即时写入)并查看一切有多慢。
有时文件只是暂时存在......程序会执行一些工作并在工作完成后立即删除文件。如果你延迟了这些写入,你可能会因为一开始就没有写过它们而逃脱惩罚。
是否不会有因 IO 错误而导致写入失败的危险?
哦,绝对是。在这种情况下,通常整个文件系统都会进入只读模式,一切都很糟糕。但这种情况很少发生,因此失去总体性能优势是没有意义的。
答案2
这种方法背后的哲学是什么?
效率(更好地利用磁盘特性)和性能(允许应用程序在写入后立即继续)。
为什么数据不立即写入?
主要优点是操作系统可以自由地重新排序和合并连续的写入操作,以提高带宽使用率(更少的操作和更少的寻道)。当请求少量大型操作时,硬盘性能会更好,而应用程序往往需要大量小型操作。另一个明显的优化是,当同一块在短时间内被多次写入时,操作系统还可以删除除最后一次写入之外的所有写入,或者如果同时删除了受影响的文件,甚至可以一起删除一些写入。
这些异步写入完成后系统write
调用已返回。这是第二个也是用户最明显的优势。异步写入可以加快应用程序的速度,因为它们可以自由地继续工作,而无需等待数据实际存储在磁盘上。对于读操作也实现了相同类型的缓冲/缓存,其中最近或经常读取的块被保留在内存中而不是再次从磁盘读取。
是否不会有因 IO 错误而导致写入失败的危险?
不必要。这取决于所使用的文件系统和适当的冗余。如果数据可以保存在其他地方,则 I/O 错误可能是无害的。像 ZFS 这样的现代文件系统可以自我修复坏磁盘块。另请注意,I/O 错误不会使现代操作系统崩溃。如果它们发生在数据访问期间,则只需将它们报告给受影响的应用程序即可。如果它们发生在结构元数据访问期间并使文件系统面临风险,则可能会以只读方式重新安装或使其无法访问。
如果操作系统崩溃、断电或硬件故障,也存在轻微的数据丢失风险。这就是为什么必须 100% 确定数据位于磁盘上的应用程序(例如数据库/金融应用程序)执行效率较低但更安全的同步写入的原因。为了减轻性能影响,许多应用程序仍然使用异步写入,但最终在用户显式保存文件时同步它们(例如 vim、文字处理器)。
另一方面,绝大多数用户和应用程序不需要也不关心同步写入所提供的安全性。如果发生崩溃或断电,唯一的风险通常是丢失最后 30 秒的数据。除非涉及金融交易或类似的事情,这意味着成本远大于 30 秒的时间,否则异步写入在性能上的巨大收益(这不是幻觉而是非常真实的)将大大超过风险。
最后,同步写入不足以保护写入的数据。如果您的应用程序确实需要确保无论发生什么情况,其数据都不会丢失,则需要在多个磁盘和多个地理位置上进行数据复制,以抵御火灾、洪水等灾难。
答案3
异步、缓冲 I/O 在 Linux 甚至 Unix 之前就已被使用。 Unix 有它,它的所有分支也有。
以下是 Ritchie 和 Thompson 在他们的 CACM 论文中所写的内容UNIX 分时系统:
对于用户来说,文件的读取和写入似乎都是同步且无缓冲的。也就是说,从读取调用返回后,数据立即可用,相反,在写入之后,用户的工作空间可以被重用。事实上,系统维护着相当复杂的缓冲机制,大大减少了访问文件所需的 I/O 操作数量。
在您的问题中,您还写道:
是否不会有因 IO 错误而导致写入失败的危险?
是的,写入可能会失败,而程序可能永远不会知道这一点。虽然这从来都不是一件好事,但在 I/O 错误产生系统恐慌的情况下,可以将其影响最小化(在某些操作系统上,这是可配置的 - 系统可以继续运行,但受影响的文件系统不会出现恐慌)未安装或安装为只读)。然后可以通知用户该文件系统上的数据可疑。并且可以主动监控磁盘驱动器以查看其是否生长缺陷清单正在快速增加,这表明驱动器出现故障。
BSD 添加了fsync
系统调用,因此程序可以确定其文件数据在继续之前已完全写入磁盘,并且后续的 Unix 系统提供了执行同步写入的选项。 GNU dd 有一个选项conv=fsync
可以确保在命令退出之前所有数据都已写出。当写入速度较慢的可移动闪存驱动器时,它会派上用场,因为缓冲的数据可能需要几分钟才能写出。
文件损坏的另一个来源是系统突然关闭,例如由于断电。几乎所有当前系统都支持干净/肮脏在他们的文件系统中标记。该标志设置为干净的当没有更多数据要写出并且文件系统即将被卸载时,通常在系统关闭期间或通过手动调用umount
.fsck
如果系统检测到文件系统没有完全关闭,系统通常会在重新启动时运行。
答案4
它并不是 Linux 独有的,它被称为页面缓存(Linux 做得很好)。也可以看看http://linuxatemyram.com/;因此,如果写入文件,几秒钟后再次读取,通常不需要磁盘 I/O。
主要优点是,在许多系统上,有大量 RAM,其中一些可以被内核用作缓存。因此某些文件操作可以利用此缓存。此外,磁盘 I/O 时间比 RAM 慢很多(对于 SDD 通常慢数千倍,对于机械硬盘慢近一百万倍)。
应用程序代码可以提供有关此缓存的提示:请参阅例如posix_fadvise(2)&疯狂的维斯(2)