我有一个 C 应用程序,有时无法打开存储在/tmp
共享中的文件。
这是相关的代码块:
// open file and start parsing
notStdin = strcmp(inFile, "-");
if (notStdin) {
coordsIn = fopen(inFile, "r"); <----- inFile = file that I want to open
if (coordsIn == NULL) {
fprintf(stderr, "ERROR: Could not open coordinates file: %s\n\t%s\n", inFile, strerror(errno));
exit(EXIT_FAILURE);
}
}
else
coordsIn = stdin;
在八到十次试验中,我得到一个NULL
FILE 指针。这是一个示例错误消息:
ERROR: Could not open coordinates file: /tmp/coordinates.txt
File or directory does not exist
但是,该文件/tmp/coordinates.txt
确实存在,因为我可以使用标准实用程序(如head
、cat
或more
等)打开它。
/tmp/coordinates.txt
不同试用文件的权限是一样的。
以下是结果uname -a
:
$ uname -a
Linux hostname 2.6.18-128.2.1.el5 #1 SMP Wed Jul 8 11:54:47 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
如果我使用inFile
存储在不同的非/tmp
共享中的不同,那么我不会观察到这种症状。
是否有任何事情会导致fopen()
存储在/tmp
共享中的文件失败?我可以采取其他故障排除步骤吗?
打开的文件太多?
您的程序是否打开大量文件?也许您的文件描述符用完了?如果是这种情况,这里是关于如何更改程序、shell 和操作系统的链接。要查看您正在使用您的程序的许多人:
在我的 Ubuntu 系统上,shell 限制为 1024,包括 stdout、stderr 和 stdin。这是在 /etc/security/limits.conf 中设置的。下面的小程序显示了这一点:
当我运行它时,它会打印退出状态为 1 的“1021”。
检查系统错误:
更一般地说,您可以随时检查 dmesg 或 /var/log/messages 的输出是否有任何错误。
观察文件,看看是否有其他东西弄乱了它:
也许文件不存在,有什么东西正在从你下面删除它?您可能希望使用 inotify 来查看文件上的所有事件,或者使用 intify 的工具,例如incron或inotify-tools。
也许某个程序正在锁定这个文件?它可以是您的程序的另一个副本。
有什么
lsof /tmp/coordinates.txt
表现吗?我想不出 /tmp 有什么特别的地方应该使文件间歇性地不存在。/tmp 只是一个普通目录,具有稍微特殊的权限,允许每个人乱搞,但限制非 root 用户不拥有文件以删除它们。
您的程序是否有任何外部修改/更改该文件,或者您的程序是否是多线程的并使用该文件?如果是这样,它可能是一个竞争条件。
要检查是否是这种情况,您可以按照 Kyle 的建议使用 inotify (您可能在删除并从事件中移动之后)来查看文件到底发生了什么。
或者,您可以尝试统计文件并查看它的 ctime 和/或 mtimes 是否与 fopen 因 ENOENT 失败时一致。
维姆?
只是一个疯狂的猜测。发生此问题时,您是否在 vim 中打开了 /tmp/coordinates.txt 文件?
我在 vim 中编辑的文件从文件系统中消失并在不久后重新出现时遇到了问题。我实际上从未见过 ls 丢失的文件,但我有例如 gcc 在尝试打开文件时失败,只是在第二次尝试中成功。
这不是一个非常罕见的神器,它在白天经常发生。
我不知道解决方案是什么,但我知道我观察到了同样的问题,而不仅仅是在 /tmp 上。它可能发生在 NFS 挂载上,甚至本地挂载上,例如 /lib。我今天发现的一个问题通过(不正确地)打开、查找、读取一点并关闭同一个文件数千次(而不是仅在整个操作中保持文件打开)来重现此问题。偶尔,fopen() 之一会因 ENOENT 错误而失败。这并没有像一个人建议的那样打开太多文件——它实际上认为文件一瞬间不存在。
我一直在寻找其他人是否有类似的问题,这是我最接近的。不过,我没有任何答案,只是在寻找解决方案。
我不认为这是 Linux(或 RHEL)特有的,因为我没有在任何地方看到这种情况,只是在一个环境中。我不知道可能导致此问题的环境有什么不同(存在差异)。虽然看到它在 RHEL5 中没有得到修复并不好(我在 RHEL4 上看到它)。