[H] 这有多严重,今天还是过去三年的任何时候?
典型应用程序处理数据。他们消耗一些输入,并产生结果。因此,有两种一般情况下close()
可能会返回错误:关闭输入(只读?)文件时,以及关闭刚刚生成或修改的文件时。
close()
返回错误的已知情况特定于将数据写入/刷新到永久存储。特别是,操作系统通常会在本地缓存数据,然后再实际写入永久存储(at close()
、fsync()
或fdatasync()
);这在远程文件系统中很常见,这也是手册页上提到 NFS 的原因。
关闭只读输入文件时,我从未遇到过错误。我能想到的在现实生活中使用任何常见文件系统可能发生的所有情况都是发生灾难性故障的情况,例如内核数据结构损坏。如果发生这种情况,我认为close()
错误不能是某些事情严重错误的唯一迹象。
在远程文件系统上写入文件时close()
,如果本地网络容易出现故障或只是丢弃大量数据包,则时间错误非常普遍。作为最终用户,我希望我的应用程序在写入文件时告诉我是否有错误。通常与远程文件系统的连接完全断开,写入新文件失败的事实是用户的第一个指标。
如果不检查close()
返回值,应用程序就会对用户撒谎。它将指示(如果不是其他情况,则缺少错误消息)该文件被正确写入,而实际上它不是,并且应用程序被告知如此;该应用程序只是忽略了该指示。如果用户像我一样,他们会对应用程序非常不满。
问题是,用户数据对您来说有多重要?大多数当前的应用程序程序员根本不在乎。Basile Starynkevitch(在对原始问题的评论中)是绝对正确的;检查close()
错误不是大多数程序员费心去做的事情。
我认为这种态度是应受谴责的;无视用户数据的骑士。
不过,这是很自然的,因为用户无法明确指出哪个应用程序损坏了他们的数据。根据我的经验,最终用户通常会归咎于操作系统、硬件、开源或免费软件,或者本地 IT 支持;因此,对于程序员来说,没有压力,社会或其他方面的压力。因为只有程序员才知道诸如此类的细节,而大多数程序员并不关心,所以没有改变现状的压力。
(我知道上面说的话会让很多程序员讨厌我的胆量,但至少我是诚实的。我指出这样的事情得到的典型反应是,这种情况非常罕见,它会是浪费资源来检查这一点。这可能是真的.. 但我愿意花更多的 CPU 周期并向程序员多付几个百分点,如果这意味着我的机器实际上可以更可预测地工作,并告诉我是否它失去了情节,而不是默默地破坏了我的数据。)
有没有一个简单的、可重复的例子来说明这种无声的数据丢失?
我知道三种方法:
使用 U 盘,在决赛之后write()
但在close()
. 不幸的是,大多数 USB 记忆棒的硬件无法承受这种情况,因此您最终可能会将 USB 记忆棒变砖。根据文件系统的不同,您的内核也可能会出现恐慌,因为大多数文件系统都是在假设这永远不会发生的情况下编写的。
设置 NFS 服务器,并通过使用 iptables 丢弃 NFS 服务器和客户端之间的所有数据包来模拟间歇性数据包丢弃。确切的场景取决于服务器和客户端、挂载选项和使用的版本。但是,使用两个或三个虚拟机设置测试台应该相对容易。
使用自定义文件系统来模拟一次写入错误close()
。当前的内核不允许您强制卸载 tmpfs 或环回挂载,只有 NFS 挂载,否则这很容易通过在最终写入之后但在close()
. (如果该文件系统上有打开的文件,当前内核简单地拒绝 umount。)对于应用程序测试,创建一个 tmpfs 的变体,close()
如果文件模式表明它是可取的(例如,其他可写但不是其他-可读或其他可执行文件,即。-??????-w-
)将非常容易且安全。它实际上不会损坏数据,但如果内核在关闭时间报告(风险)数据损坏,它可以很容易地检查应用程序的行为。