2010-07-29 9 views
6

Estoy usando un código como el siguiente para comprobar si un archivo ha sido creado antes de continuar, es que el archivo aparece en el buscador de archivos mucho antes de que sea detectado por stat ... ¿hay algún problema al hacer esto?usando stat para detectar si existe un archivo (¿lento?)

//... do something 

struct stat buf; 

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

//... do something else 

¿Existe alguna otra forma de verificar si existe un archivo?

+0

Qué archivo? ¿Qué está escribiendo el archivo? ¿Estás seguro de que el archivo no se escribe con un nombre ligeramente diferente y luego se renombra en el último momento? –

+0

Estoy usando konqueror, pero dolphin también notifica a mi antes que stat. el archivo está siendo escrito por una aplicación que escribí, así que sé qué y dónde debe escribirse. Además, el archivo es un archivo vacío que estoy escribiendo solo para indicar que se ha completado un proceso. –

+0

¿Cuánto tiempo hace que se está refiriendo a este retraso? ¿Está en el orden de microsegundos o minutos? No debería haber ninguna razón por la cual 'stat()' no pueda indicar que el archivo existe cuando realmente lo hace. Sospecho que hay algo más que sucede aquí que aún no has reconocido. –

Respuesta

3

La llamada al sistema "stat" recopila información diferente sobre el archivo, como, por ejemplo, un número de enlaces duros que apuntan a él o su número "inode". Es posible que desee consultar la llamada al sistema de "acceso" que puede usar para realizar la verificación de existencia solo especificando el indicador "F_OK" en "modo".

Sin embargo, hay un pequeño problema con su código. Pone el proceso a dormir por un segundo cada vez que busca un archivo que aún no existe. Para evitar eso, debe usar la API inotify, como lo sugiere Jerry Coffin, para que el kernel le notifique cuando el archivo que está esperando está allí. Tenga en cuenta que inotify no le notifica si el archivo ya está allí, por lo que, de hecho, necesita usar tanto "access" como "inotify" para evitar una condición de carrera cuando comenzó a buscar un archivo justo después de que se creó.

No hay forma mejor o más rápida de verificar si el archivo existe. Si su buscador de archivos aún muestra el archivo un poco más rápido de lo que este programa lo detecta, entonces la idea de Greg Hewgill sobre el cambio de nombre probablemente esté teniendo lugar.

Aquí es un ejemplo de código C++ que pone en marcha un reloj de inotify, comprueba si el archivo ya existe y espera a que de otro modo: el navegador

#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 pregunta, es que dormir (1) es un problema tan grande ... un par de segundos de retraso no es un problema, y ​​eso es lo máximo que esperaría al agregar la llamada de espera. –

+0

No, eliminar el sueño es solo una búsqueda de la excelencia en lugar de una solución de problemas si estamos hablando de 10 a 60 segundos de retraso aquí. Greg Hewgill hace preguntas correctas sobre la replicación similar a NFS y diferentes máquinas. Esas cosas son las causas más probables. Además, hay una llamada al sistema "waitpid" que puede usar para esperar a que el proceso finalice en lugar de crear/sondear un archivo. –

+0

Esto también tiene una condición de carrera en el hecho de que no existen garantías de que el archivo exista después de que la notificación o la función de acceso llame. Solo en el momento de las llamadas. Y, de hecho, es probable que se eviten las pruebas para ver si existe un archivo. Debe asumir que el archivo existe y manejar el caso si no puede acceder o perderlo mientras trabaja con él. Ejemplo 1: el archivo existe pero no tiene acceso. Ejemplo 2: el archivo "desaparece" porque el montaje desaparece (NFS). – Rahly

4

Usando inotify, puede hacer arreglos para que el kernel le avise cuando se produce un cambio en el sistema de archivos (como la creación de un archivo). Esto bien puede ser lo que usa su buscador de archivos para conocer el archivo tan rápidamente.

1

su código verificará si el archivo está allí cada segundo. puede usar inotify para obtener un evento en su lugar.

Cuestiones relacionadas