我正在使用下面的代碼來檢查文件是否在繼續之前被創建,事情是文件在文件瀏覽器中出現之前很久檢測到stat ...這樣做有問題嗎?使用stat來檢測文件是否存在(很慢?)
//... do something
struct stat buf;
while(stat("myfile.txt", &buf))
sleep(1);
//... do something else
或者有更好的方法來檢查文件是否存在?
我正在使用下面的代碼來檢查文件是否在繼續之前被創建,事情是文件在文件瀏覽器中出現之前很久檢測到stat ...這樣做有問題嗎?使用stat來檢測文件是否存在(很慢?)
//... do something
struct stat buf;
while(stat("myfile.txt", &buf))
sleep(1);
//... do something else
或者有更好的方法來檢查文件是否存在?
「stat」系統調用正在收集有關文件的不同信息,例如,指向它的多個硬鏈接或其「inode」編號。您可能需要查看「access」系統調用,您只能通過在「mode」中指定「F_OK」標誌來執行存在檢查。
但是,您的代碼存在一些小問題。它會在每次檢查尚不存在的文件時讓進程休眠一秒。爲了避免這種情況,您必須按照Jerry Coffin的建議使用inotify API,以便在您等待的文件存在時通過內核獲得通知。請記住,如果文件已經存在,inotify不會通知您,所以實際上您需要同時使用「access」和「inotify」以避免在創建文件之後開始監視文件時的競爭狀況。
沒有更好或更快的方法來檢查文件是否存在。如果您的文件瀏覽器仍然顯示文件稍快於此程序檢測到它,那麼Greg Hewgill關於重命名的想法可能正在發生。
這裏是一個C++代碼示例設置了一個inotify的手錶,如果文件已經存在,檢查和否則爲它等待:
#include <cstdio>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/inotify.h>
int
main()
{
const std::string directory = "/tmp";
const std::string filename = "test.txt";
const std::string fullpath = directory + "/" + filename;
int fd = inotify_init();
int watch = inotify_add_watch (fd, directory.c_str(),
IN_MODIFY | IN_CREATE | IN_MOVED_TO);
if (access (fullpath.c_str(), F_OK) == 0)
{
printf ("File %s exists.\n", fullpath.c_str());
return 0;
}
char buf [1024 * (sizeof (inotify_event) + 16)];
ssize_t length;
bool isCreated = false;
while (!isCreated)
{
length = read (fd, buf, sizeof (buf));
if (length < 0)
break;
inotify_event *event;
for (size_t i = 0; i < static_cast<size_t> (length);
i += sizeof (inotify_event) + event->len)
{
event = reinterpret_cast<inotify_event *> (&buf[i]);
if (event->len > 0 && filename == event->name)
{
printf ("The file %s was created.\n", event->name);
isCreated = true;
break;
}
}
}
inotify_rm_watch (fd, watch);
close (fd);
}
有一個問題,睡眠(1)是一個如此大的問題......幾秒鐘的延遲不是問題,這是我期望添加睡眠呼叫的最多。 – 2010-07-29 14:57:05
不,消除睡眠只是追求卓越,而不是解決問題,如果我們在這裏談論10到60秒的延遲。 Greg Hewgill就NFS類複製和不同機器問題提出正確的問題。這些事情是最可能的原因。 此外,還有一個「waitpid」系統調用,您可以使用它來等待進程完成而不是創建/輪詢文件。 – 2010-07-29 15:13:04
這也有競爭條件的事實,即在通知或訪問函數調用後沒有保證文件存在的事實。只在通話時。實際上,應該避免測試是否存在文件。你應該假設文件存在,並處理這種情況,如果你無法訪問它或在使用它時丟失它。示例1:文件存在但您無權訪問。示例2:由於掛載消失(NFS),文件「消失」。 – Rahly 2016-09-15 17:13:44
使用inotify,您可以安排內核在發生文件系統更改(如文件創建)時通知您。這很可能是您的文件瀏覽器用來快速瞭解文件的原因。
你的代碼會檢查文件是否每秒都在那裏。您可以使用inotify來取代事件。
什麼文件瀏覽器?什麼是寫文件?你確定這個文件沒有被寫成一個稍微不同的名字,然後在最後一刻被重命名嗎? – 2010-07-29 13:28:14
我使用的是konqueror,但海豚也比stat更早通知我。該文件正在寫我所寫的一個應用程序,所以我知道應該寫什麼和在哪裏。此外,該文件是我寫的空文件,只是爲了表示進程已完成。 – 2010-07-29 13:50:28
你所指的這段延遲時間有多長?它是微秒級還是分鐘級?應該沒有理由說明爲什麼'stat()'應該在它確實存在時指示文件存在。我懷疑你還沒有意識到還有其他事情在發生。 – 2010-07-29 13:53:55