2010-07-29 6 views
6

Ich verwende Code wie den folgenden, um zu prüfen, ob eine Datei erstellt wurde, bevor sie fortfährt, ding ist die Datei wird im Dateibrowser angezeigt, viel bevor es ist per stat erkannt ... gibt es ein Problem damit?Verwenden von stat, um zu erkennen, ob eine Datei existiert (langsam?)

//... do something 

struct stat buf; 

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

//... do something else 

alternativ gibt es eine bessere Möglichkeit zu überprüfen, ob eine Datei existiert?

+0

Welche Datei-Browser? Was ist das Schreiben der Datei? Sind Sie sicher, dass die Datei nicht unter einem etwas anderen Namen geschrieben und dann im letzten Moment umbenannt wird? –

+0

Ich benutze Konqueror, aber Delphin benachrichtigt auch meine früheren als stat. Die Datei wird von einer App geschrieben, die ich geschrieben habe, damit ich weiß, wo und wo sie geschrieben werden sollte. Außerdem ist die Datei eine leere Datei, die ich gerade schreibe, um zu signalisieren, dass ein Prozess abgeschlossen ist. –

+0

Wie lange ist diese Verzögerungszeit gemeint? Liegt es in der Größenordnung von Mikrosekunden oder Minuten? Es sollte keinen Grund geben, warum 'stat()' nicht darauf hinweisen sollte, dass die Datei existiert, wenn dies tatsächlich der Fall ist. Ich vermute, dass hier noch etwas anderes vor sich geht, das Sie noch nicht erkannt haben. –

Antwort

3

Der Systemaufruf "stat" sammelt verschiedene Informationen über die Datei, wie z. B. eine Anzahl von Hardlinks, die auf sie verweisen, oder ihre "Inode" -Nummer. Vielleicht möchten Sie sich den Systemaufruf "access" ansehen, mit dem Sie die Existenzprüfung durchführen können, indem Sie im Modus "F_OK" angeben.

Es gibt jedoch ein kleines Problem mit Ihrem Code. Es versetzt den Prozess jedes Mal für eine Sekunde in den Ruhezustand, wenn er nach Dateien sucht, die noch nicht existieren. Um dies zu vermeiden, müssen Sie die von Jerry Coffin vorgeschlagene API inotify verwenden, um vom Kernel benachrichtigt zu werden, wenn die Datei, auf die Sie warten, vorhanden ist. Beachten Sie, dass inotify Sie nicht benachrichtigt, wenn die Datei bereits vorhanden ist. In der Tat müssen Sie sowohl "access" als auch "inotify" verwenden, um eine Race-Bedingung zu vermeiden, wenn Sie nach der Erstellung nach einer Datei suchen.

Es gibt keinen besseren oder schnelleren Weg zu prüfen, ob eine Datei existiert. Wenn Ihr Dateibrowser die Datei immer noch etwas schneller anzeigt, als das Programm sie erkennt, dann wird wahrscheinlich Greg Hewgills Idee der Umbenennung stattfinden.

Hier ist ein C++ Codebeispiel, das eine inotify Uhr einrichtet, überprüft, ob Datei bereits vorhanden und wartet es anders:

#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); 
} 
+0

eine Frage, ist Schlaf (1) so ein großes Problem ... ein paar Sekunden Verzögerung ist kein Problem, und das ist die meisten, die ich von der Schlafanruf hinzufügen würde erwarten. –

+0

Nein, Schlaf zu eliminieren ist nur ein Streben nach Exzellenz und keine Problemlösung, wenn wir hier von 10 bis 60 Sekunden Verzögerung sprechen. Greg Hewgill stellt Fragen zu NFS-ähnlicher Replikation und verschiedenen Maschinen. Diese Dinge sind die wahrscheinlichsten Ursachen. Außerdem gibt es einen "waitpid" -Systemaufruf, mit dem Sie darauf warten können, dass der Prozess beendet wird, anstatt eine Datei zu erstellen/abzurufen. –

+0

Dies hat auch eine Race-Bedingung in der Tatsache, dass es keine Garantien gibt, dass die Datei nach dem Notify OR Zugriff Funktion besteht. Nur zum Zeitpunkt der Anrufe. Und tatsächlich sollte das Testen, um zu sehen, ob eine Datei existiert, wahrscheinlich vermieden werden. Sie sollten davon ausgehen, dass die Datei existiert, und den Fall behandeln, wenn Sie nicht darauf zugreifen können oder ihn verlieren, während Sie damit arbeiten. Beispiel 1: Datei existiert, aber Sie haben keinen Zugriff. Beispiel 2: Datei "geht weg", weil das Mount verschwindet (NFS). – Rahly

4

Mit inotify können Sie veranlassen, dass der Kernel Sie benachrichtigt, wenn eine Änderung am Dateisystem (z. B. eine Dateierstellung) stattfindet. Dies kann gut sein, was Ihr Dateibrowser verwendet, um so schnell über die Datei zu wissen.

1

Ihr Code wird prüfen, ob die Datei jede Sekunde da ist. Sie können stattdessen inotify verwenden, um ein Ereignis zu erhalten.

Verwandte Themen