我有一个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;
在8到10次试验中,我得到一个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 :
$ 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和操作系统的链接(如果是这种情况)。 看到你用你的程序很多:
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的工具,如incron或inotify-tools 。
也许有些程序正在locking这个文件? 它可以是你的程序的另一个副本。
lsof /tmp/coordinates.txt显示什么?
我不能想到什么特殊的/ tmp应该使文件间歇性地不在那里。 / tmp只是一个普通的目录,稍许特殊的权限允许每个人都搞乱,但限制非root用户不拥有文件来删除它们。
你的程序是否有修改/更改该文件的外部,或者,你的程序是multithreading的,并且使用该文件? 如果是的话,这可能是一个竞赛条件。
要检查是否属于这种情况,您可以使用inotify,正如Kyle所build议的(您可能在删除并从事件中移出之后)来查看文件的具体情况。
或者,您可以尝试对文件进行统计,并查看在使用ENOENT失败时ctime和/或mtimes是否一致。
Vim的?
只是一个疯狂的猜测。 在vim中打开/tmp/coordinates.txt文件时是否出现此问题?
我在vim中编辑的文件遇到问题,从文件系统中消失,很快就重新出现。 我从来没有见过用ls丢失这个文件,但是我有gcc失败,试图打开文件,只能在第二次尝试中成功。
这不是非常罕见的神器,它在白天经常发生。
我不知道解决scheme是什么,但我知道我已经观察到了这个问题,而不仅仅是/ tmp。 它可以通过NFS挂载,甚至本地挂载,如/ lib。 我今天发现的一个问题通过(不正确地)打开,寻找,阅读一些并closures同一文件几千次(而不是仅仅保持整个操作的文件打开)来再现这个问题。 零星地,其中一个fopen()会失败,并带有ENOENT错误。 这不是一个人build议的太多的文件打开 – 它从字面上认为该文件不是在那里一秒钟。
我一直在寻找是否有其他人有类似的问题,这是最接近我来了。 我没有任何答案,只是寻找解决scheme。
我不认为这是Linux(或RHEL)特有的,因为我不在任何地方看到这一点,只是在一个环境中。 我不知道可能导致这个问题的环境有什么不同(有差异)。 虽然看不到它在RHEL5中是不是固定的(我在RHEL4上看到它)。