6

次のようなコードを使用して、続行する前にファイルが作成されているかどうかを確認しています。これは、統計によって検出されるずっと前にファイルがファイルブラウザに表示されていることです...これを行うことに問題はありますか?

//... do something

struct stat buf;

while(stat("myfile.txt", &buf))
  sleep(1);

//... do something else

あるいは、ファイルが存在するかどうかを確認するためのより良い方法はありますか?

4

3 に答える 3

4

inotifyを使用すると、ファイルシステムへの変更(ファイルの作成など)が発生したときにカーネルが通知するように調整できます。これは、ファイルブラウザがファイルをすばやく知るために使用しているものかもしれません。

于 2010-07-29T13:37:10.487 に答える
3

「stat」システム呼び出しは、ファイルに関するさまざまな情報を収集します。たとえば、ファイルを指すハードリンクの数やその「inode」番号などです。「モード」で「F_OK」フラグを指定するだけで存在チェックを実行できる「アクセス」システムコールを確認することをお勧めします。

ただし、コードには少し問題があります。まだ存在しないファイルをチェックするたびに、プロセスを1秒間スリープ状態にします。これを回避するには、Jerry Coffinによって提案されているように、待機しているファイルが存在するときにカーネルから通知を受け取るために、inotifyAPIを使用する必要があります。inotifyはファイルがすでに存在する場合は通知しないため、実際には、ファイルの作成直後にファイルの監視を開始したときに競合状態を回避するために、「access」と「inotify」の両方を使用する必要があります。

ファイルが存在するかどうかを確認するためのより良いまたはより速い方法はありません。それでもファイルブラウザにこのプログラムが検出するよりもわずかに速くファイルが表示される場合は、名前の変更に関するGregHewgillの考えがおそらく行われています。

これは、inotifyウォッチをセットアップし、ファイルがすでに存在するかどうかを確認し、存在しない場合はそれを待機するC++コードの例です。

#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);
}
于 2010-07-29T14:35:00.387 に答える
1

コードは、ファイルが毎秒そこにあるかどうかをチェックします。代わりに、 inotifyを使用してイベントを取得できます。

于 2010-07-29T13:38:14.587 に答える