【发布时间】:2013-05-12 14:33:21
【问题描述】:
我正在使用打开、读取和关闭进行一些基本的文件读取(文件以 O_RDONLY 访问模式打开)。
当需要关闭文件时,我想不出一个好的方法来处理可能的文件关闭错误以确保文件被正确关闭。
有什么建议吗?
【问题讨论】:
标签: c linux file-io error-handling
我正在使用打开、读取和关闭进行一些基本的文件读取(文件以 O_RDONLY 访问模式打开)。
当需要关闭文件时,我想不出一个好的方法来处理可能的文件关闭错误以确保文件被正确关闭。
有什么建议吗?
【问题讨论】:
标签: c linux file-io error-handling
根据我的经验,close 即使失败了也会成功。这有几个原因。
我怀疑close 在某些操作系统上开始失败的主要原因之一是 AFS。 AFS 是 80 年代的分布式文件系统,具有有趣的语义 - 您的所有写入都在本地缓存中完成,并且在您关闭文件时将数据写入服务器。 AFS 还使用一段时间后过期的令牌进行了加密身份验证。因此,您最终可能会遇到一个有趣的情况,您对文件所做的所有写入都是在令牌有效时完成的,但实际上与文件服务器通信的 close 可以使用过期令牌完成,这意味着您写入的所有数据到本地缓存丢失。这就是为什么close 需要与用户沟通出现问题的原因。大多数文件编辑器都能正确处理这个问题(例如,emacs 拒绝将缓冲区标记为不脏),但我很少看到其他应用程序可以处理这个问题。
话虽如此,close 无论如何也不会失败。 close 在exit、exec(witch close-on-exec 文件描述符)期间是隐式的,并且会导致转储核心崩溃。这些是你不能失败的情况。您不能因为关闭文件描述符失败而让exit 或崩溃失败。当exit 失败时你会怎么做?碰撞?如果崩溃失败怎么办?在那之后我们跑到哪里去?此外,由于几乎没有人检查close 中的错误,如果失败很常见,您最终会导致文件描述符泄漏和信息泄漏(如果我们未能在生成非特权进程之前关闭某些文件描述符怎么办?)。所有这一切对于操作系统来说都太危险了,所以我看过的所有操作系统(*BSD、Linux、Solaris)都会关闭文件描述符,即使底层文件系统关闭操作失败。
实际上,这意味着您只需调用close 并忽略它返回的任何错误。如果你有一个优雅的方式来处理它像编辑器一样失败,你可以向用户发送一条消息,让用户解决问题并重新打开文件,写下数据并尝试再次关闭。不要在循环或其他方式中自动执行任何操作。 close 中的错误超出了您在应用程序中的控制范围。
【讨论】:
我想最好的办法是重试几次,尝试之间有一些短暂的延迟,然后记录问题并继续。
manual page for close() 提到 EINTR 是一个可能的错误,这就是为什么重新尝试会有所帮助。
如果您的程序无论如何都要退出,我不会太担心这种类型的错误检查,因为无论如何您分配的任何资源都将被操作系统取消分配(大多数/典型桌面/服务器平台,即)。
【讨论】:
close() 似乎是个坏主意:lkml.org/lkml/2002/7/17/165
close 返回错误的操作系统(这本身就是一个糟糕的主意),文件描述符也会因错误而关闭。再次调用close 要么不执行任何操作,要么关闭其他线程打开的无关文件描述符。