2012-09-09 8 views
35

Tengo un descriptor de archivo almacenado en una variable, por ejemplo var. ¿Cómo puedo verificar si ese descriptor es válido en una etapa posterior?¿Cómo verificar si un descriptor de archivo dado almacenado en una variable sigue siendo válido?

fdvar1= open(.....); 
    fdvar2 = fdvar1;  // Please ignore the bad design 

    .... 
    // lots of loops , conditionals and threads. It can call close(fdvar2) also. 
    .... 

    if(CheckValid(fdvar1)) // How can I do this check ? 
    write(fdvar1, ....); 

Ahora quiero comprobar si var1 (que aún conserva el descriptor abierto) sigue siendo válido. ¿Alguna API para eso?

+2

¿Por qué la FD copiado en el nivel C en lugar de a nivel de sistema operativo? –

+1

Consulte la página del manual para ['dup'] (http://linux.die.net/man/2/dup). –

+2

Incluso si puede verificar la validez, el resultado es prácticamente inútil, porque es posible que otro archivo abierto reciba el mismo descriptor después de que se cerró el original. – interjay

Respuesta

58

fcntl(fd, F_GETFD) es la forma más barata canónica para comprobar que fd es un descriptor de fichero abierto válido. Si necesita realizar un lote de comprobación, usar poll con un tiempo de espera cero y el miembro events establecido en 0 y comprobar POLLNVAL en revents después de devolver es más eficiente.

Dicho esto, la operación "verificar si un identificador de recurso determinado sigue siendo válido" casi siempre es fundamentalmente incorrecta. Después de que se libera un identificador de recurso (por ejemplo, un fd es close d), su valor puede reasignarse al siguiente recurso que asigne. Si hay referencias restantes que podrían usarse, operarán erróneamente el nuevo recurso en lugar del anterior. Por lo tanto, la respuesta real es probablemente: si aún no conoce la lógica de su programa, tiene importantes errores de lógica fundamental que deben corregirse.

+1

@R Suponiendo que estoy intentando implementar una biblioteca que maneje un FD, por ejemplo, la biblioteca de pipas, y yo soy el que pasa los argumentos de FD a los programas que usarán mi biblioteca, es una mala práctica probarlo. ¿validación? ¿O es obligatorio? – petric

+0

@ petric: no entiendo tu pregunta. Como respuesta general, voy a decir que sí, que es malo (y sin sentido) "probar la validación de FD", pero si tiene inquietudes específicas sobre lo que está haciendo, probablemente debería publicar una nueva pregunta al respecto (y refiriéndose a esta pregunta/respuesta) en lugar de preguntar en un comentario. –

21

Usted puede utilizar la función fcntl():

int fd_is_valid(int fd) 
{ 
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF; 
} 
+3

'F_GETFD' es, en principio, más barato, ya que solo desreferencia el descriptor de archivo (process-local) en el espacio del kernel, no la descripción subyacente del archivo abierto (process-shared) al que se refiere. –

+0

@R .. gracias por la información, corregida. –

+1

Debe establecer 'errno' en cero antes de llamar a' fcntl'. 'errno' podría ser igual a' EBADF' antes de llamar a su función y 'fcntl' solo lo cambiará en caso de error. – Bilow

3

No creo que haya ninguna función que pueda indicarle si el descriptor aún es válido. El descriptor es típicamente solo un entero pequeño como 6 y su libc puede elegir reutilizar ese número si cierra el archivo y abre uno nuevo más tarde.

En su lugar, debe considerar usar dup() para copiar el descriptor de archivo. Al duplicar el descriptor de archivo en lugar de utilizar el mismo descriptor en varios lugares, puede ser más fácil para usted saber si el descriptor de archivo sigue siendo válido. Solo debe recordar cerrar el descriptor original y el duplicado cuando haya terminado.

+0

Incorrecto. Se mi y R .. 's respuesta. –

+3

David es "correcto" porque no se puede determinar si un descriptor es "* todavía * válido". Puede decir si es válido, pero esto no le da información sobre si todavía se refiere al mismo recurso o no. –

+1

Sí. Mi definición de válida es que todavía apunta a lo mismo que antes. Creo que es una buena definición porque generalmente es lo que quieres y puedes decir si el descriptor sigue siendo válido simplemente mirando el código; no depende de un comportamiento indefinido. –

3

Del artículo this foro:

int is_valid_fd(int fd) 
{ 
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF; 
} 

fcntl (GETFL) es probablemente el más barato y menos propensos a fallar operación se puede llevar a cabo en un descriptor de archivo. En particular, la especificación sugiere que no puede ser interrumpida por señales, ni se ve afectada por ningún tipo de bloqueo en cualquier lugar.

+3

¿Qué le parece si atribuimos sus fuentes a: http://cboard.cprogramming.com/networking-device-communication/93683-checking-if-file-descriptor-valid.html#post678998 – Kev

0

Me parece que si usted quiere saber si todavía señala al mismo recurso, un enfoque (no perfecto) sería fstat() el descriptor justo después de abierto y luego se puede hacer una y otra comparar los resultados. Comience por mirar .st_mode & S_IFMT y vaya desde allí - ¿es un objeto del sistema de archivos? Mira .st_dev/.st_ino. ¿Es un zócalo? Pruebe getsockname(), getpeername(). No será 100% seguro, pero puede decirle si definitivamente no es lo mismo.

-1

he resuelto este problema para mí. No sé si se puede usar con fines generales, pero para conexiones en serie funciona bien (por ejemplo,/dev/ttyUSB0).

struct stat s; 
fstat(m_fileDescriptor, &s); 

// struct stat::nlink_t st_nlink; ... number of hard links 
if(s.st_nlink < 1){ 
// treat device disconnected case 
} 

Para obtener más información, ver p. Ej. página del manual http://linux.die.net/man/2/fstat

Saludos, Flo

Cuestiones relacionadas