fopen() 无法打开 /tmp 共享上的文件

fopen() 无法打开 /tmp 共享上的文件

我有一个 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;

经过八到十次尝试后,我得到了一个NULLFILE 指针。以下是错误消息示例:

ERROR: Could not open coordinates file: /tmp/coordinates.txt
       File or directory does not exist

但是,该文件/tmp/coordinates.txt确实存在,因为我可以使用headcatmore等标准实用程序打开它。

不同试用文件的权限/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?我还可以采取其他故障排除步骤吗?

答案1

打开的文件太多?
你的程序是否正在打开很多文件数量?也许您用完了文件描述符?以下是链接关于如何更改程序、shell 和操作系统(如果是这种情况)。要查看程序中使用的许多内容,请执行以下操作:

sudo lsof | grep <PID> | wc -l

在我的 Ubuntu 系统上,shell 限制为 1024,包括 stdout、stderr 和 stdin。这是在 /etc/security/limits.conf 中设置的。以下小程序显示了这一点:

#include <stdio.h>

int count=0;

int main( void ) {
    while(1) {
        FILE *fd = fopen("foo", "r");
        if ( fd == NULL) {
            printf("%i\n", count);
            return(1);
        }
        count++;
    }
    return(0);
}

当我运行时,它会打印“1021”,退出状态为 1。

检查系统错误:
更一般地说,您可以随时检查 dmesg 或 /var/log/messages 的输出是否有任何错误。

查看文件,看看是否有其他东西干扰它:
也许该文件不存在,有什么东西正在从你这里删除它?你可能需要使用 inotify 监视所有事件在文件上,或者使用 inotify 的工具,例如因克龙或者inotify 工具

答案2

也许某个程序锁定了这个文件?它可能是你的程序的另一个副本。

lsof /tmp/coordinates.txt显示什么吗?

答案3

我想不出 /tmp 有什么特殊之处,可以让文件间歇性地不存在。/tmp 只是一个普通目录,具有稍微特殊的权限,允许任何人乱搞,但限制非 root 用户不拥有文件以删除它们。

您的程序中是否有任何外部因素正在修改/更改该文件,或者您的程序是否是多线程的并且可以使用该文件?如果是这样,则可能是竞争条件。

要检查是否是这种情况,您可以按照 Kyle 的建议使用 inotify(您可能在删除并从事件中移出后)来查看文件到底发生了什么。

或者,您可以尝试统计文件并查看它的 ctime 和/或 mtime 是否与 fopen 因 ENOENT 而失败时相一致。

答案4

我不知道解决方案是什么,但我知道我观察到了同样的问题,而且不仅仅是在 /tmp 上。它可能发生在 NFS 挂载上,甚至本地挂载上,如 /lib。我今天发现的一个问题通过(错误地)打开、查找、读取一点并关闭同一个文件数千次(而不是在整个操作过程中保持文件打开)重现了这个问题。偶尔,其中一个 fopen() 会失败并出现 ENOENT 错误。这并不是像有人所说的那样打开了太多文件——它实际上认为文件一瞬间不存在。

我一直在寻找是否有人遇到过类似的问题,这是我遇到过最接近的问题。但我没有任何答案,只是在寻找解决方案。

我不认为这是 Linux(或 RHEL)所特有的,因为我没有在任何地方看到这种情况,只在一个环境中出现过。我不知道该环境有什么不同会导致这个问题(有区别)。不过,看到 RHEL5 中没有修复这个问题(我在 RHEL4 上看到了),这可不是什么好事。

相关内容