2010-07-29 5 views
6

Sto usando un codice come il seguente per verificare se un file è stato creato prima di continuare, cosa è che il file viene mostrato nel browser di file molto prima che venga rilevato da stat ... c'è un problema con questo?usando stat per rilevare se esiste un file (lento?)

//... do something 

struct stat buf; 

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

//... do something else 

in alternativa c'è un modo migliore per verificare se esiste un file?

+0

Che lima? Cosa sta scrivendo il file? Sei sicuro che il file non venga scritto con un nome leggermente diverso e che venga rinominato all'ultimo momento? –

+0

Sto usando konqueror, ma il delfino notifica anche la mia prima di stat. il file è stato scritto da un'app che ho scritto, quindi so cosa e dove dovrebbe essere scritto. inoltre, il file è un file vuoto che sto scrivendo solo per segnalare che un processo è stato completato. –

+0

Quanto a lungo ti riferisci? È dell'ordine di microsecondi o minuti? Non dovrebbe esserci alcuna ragione per cui 'stat()' non dovrebbe indicare che il file esiste quando lo fa realmente. Sospetto che ci sia qualcos'altro che non hai ancora riconosciuto. –

risposta

3

La chiamata di sistema "stat" sta raccogliendo informazioni diverse sul file, come ad esempio un numero di collegamenti fisici che puntano ad esso o il suo numero "inode". Potresti voler vedere la chiamata di sistema "access" che puoi usare per eseguire il controllo dell'esistenza solo specificando il flag "F_OK" in "mode".

C'è, tuttavia, un piccolo problema con il codice. Mette in pausa il processo per un secondo ogni volta che controlla il file che non esiste ancora. Per evitare ciò, devi usare l'API inotify, come suggerito da Jerry Coffin, per ricevere una notifica dal kernel quando il file che stai aspettando è lì. Tieni presente che inotify non ti avvisa se il file è già lì, quindi in realtà devi utilizzare sia "access" che "inotify" per evitare una race condition quando hai iniziato a guardare un file subito dopo la sua creazione.

Non esiste un modo migliore o più rapido per verificare se il file esiste. Se il tuo browser di file mostra ancora il file leggermente più veloce di questo programma lo rileva, allora probabilmente l'idea di Greg Hewgill sulla ridenominazione è in atto.

Ecco un esempio di codice C++ che imposta un orologio inotify, controlla se il file esiste già e attende altrimenti: il browser

#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

una domanda, è dormire (1) un grande problema ... un paio di secondi di ritardo non è un problema, e questo è il massimo che mi aspetterei dall'aggiunta della chiamata di sonno. –

+0

No, eliminare il sonno è solo una ricerca dell'eccellenza piuttosto che un problem solving se stiamo parlando di un ritardo da 10 a 60 secondi. Greg Hewgill fa le giuste domande sulla replicazione simile a NFS e su macchine diverse. Quelle cose sono le cause più probabili. Inoltre, esiste una chiamata di sistema "waitpid" che è possibile utilizzare per attendere il completamento del processo invece di creare/eseguire il polling di un file. –

+0

Questo ha anche una condizione di competizione nel fatto che non ci sono garanzie che il file esista dopo che la funzione di chiamata OR di notifica chiama. Solo al momento delle chiamate. E infatti, il test per vedere se esiste un file dovrebbe probabilmente essere evitato. Dovresti presumere che il file esista e gestisca il caso se non riesci ad accedervi o lo perdi mentre lavori con esso. Esempio 1: il file esiste ma non hai accesso. Esempio 2: il file "va via" perché il mount scompare (NFS). – Rahly

4

Utilizzando inotify, è possibile organizzare la notifica al kernel quando si verifica una modifica al file system (come la creazione di un file). Questo potrebbe essere ciò che il tuo browser di file sta usando per conoscere il file così velocemente.

1

il tuo codice controllerà se il file è lì ogni secondo. puoi usare inotify per ottenere invece un evento.