¿Cómo verificar si un descriptor de archivo determinado almacenado en una variable sigue siendo válido?

6 minutos de lectura

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

  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 verificar si var1 (que aún contiene el descriptor abierto) sigue siendo válido. ¿Alguna API para eso?

  • ¿Por qué se copia el FD en el nivel C en lugar de en el nivel del sistema operativo?

    – Ignacio Vázquez-Abrams

    9 de septiembre de 2012 a las 16:18

  • Vea la página del manual para dup.

    – Un tipo programador

    9 de septiembre de 2012 a las 16:19

  • Incluso si puede verificar la validez, el resultado es en su mayoría inútil, porque es posible que otro archivo abierto haya recibido el mismo descriptor después de que se cerró el original.

    – interjay

    9 de septiembre de 2012 a las 16:20

  • Esto se menciona claramente en el ejercicio 5.4 de TLPI.

    –Eric

    5 de mayo de 2015 a las 5:52

avatar de usuario
R.. GitHub DEJAR DE AYUDAR A ICE

fcntl(fd, F_GETFD) es la forma canónica más barata de comprobar que fd es un descriptor de archivo abierto válido. Si necesita verificar mucho por lotes, use poll con un tiempo de espera cero y el events miembro establecido en 0 y verificando POLLNVAL en revents después de que regresa es más eficiente.

Dicho esto, la operación “comprobar si un identificador de recurso dado sigue siendo válido” casi siempre es fundamentalmente incorrecta. Después de que se libera un identificador de recursos (por ejemplo, un fd es closed), su valor puede reasignarse al siguiente recurso que asigne. Si hay referencias restantes que podrían usarse, operarán incorrectamente en el nuevo recurso en lugar del antiguo. Por lo tanto, la respuesta real es probablemente: si aún no lo sabe por la lógica de su programa, tiene errores lógicos fundamentales importantes que deben corregirse.

  • @R Suponiendo que estoy tratando de implementar una biblioteca que maneja un FD, por ejemplo, la biblioteca de tuberías, y yo soy el que pasa los argumentos de FD a los programas que usarán mi biblioteca, ¿sigue siendo una mala práctica probar la validación de FD? ? ¿O es obligatorio?

    –Ravid Goldenberg

    18 dic 2014 a las 8:00

  • @petric: No entiendo tu pregunta. Como respuesta general, voy a decir que sí, 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.

    – R.. GitHub DEJA DE AYUDAR A ICE

    18 de diciembre de 2014 a las 16:32

  • ¿Qué pasa si tengo un proceso padre e hijo compartiendo una canalización? En el proceso principal, cierro el extremo de lectura y escribo el extremo de la tubería. Entonces, el proceso secundario todavía tiene un final de lectura válido. ¿Como funciona esto?

    – Ayudando a Bean

    28 oct 2018 a las 10:52

  • @HelpingBean: No veo cómo eso tiene algo que ver con esta pregunta. Si tiene una pregunta real allí, publíquela como una nueva pregunta (y no dude en enviarme @ aquí con un enlace a la nueva pregunta).

    – R.. GitHub DEJA DE AYUDAR A ICE

    28 oct 2018 a las 17:58


  • Eso es interesante. Pero en caso de que esté probando una estructura que contenga algunos descriptores de archivos. Y quiero probar una función que cierra los descriptores de archivos y recupera la memoria. ¿Sería correcto verificar si los descriptores de archivo están cerrados en tal caso?

    – San Antario

    6 de abril de 2019 a las 9:26

Puedes usar el fcntl() función:

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

  • F_GETFD es más barato en principio, ya que solo elimina la referencia del descriptor de archivo (proceso local) en el espacio del kernel, no la descripción del archivo abierto subyacente (proceso compartido) al que se refiere.

    – R.. GitHub DEJA DE AYUDAR A ICE

    9 de septiembre de 2012 a las 16:22

  • deberías establecer errno a cero antes de llamar fcntl. errno podría igualar EBADF antes de llamar a su función y fcntl sólo lo cambiará en caso de error.

    – Bilow

    29 de noviembre de 2016 a las 15:08

  • @Bilow ya está comprobando un valor de retorno de -1que solo ocurre “en caso de error”, por lo que establecer errno a 0 antes de que la llamada simplemente sea redundante.

    –Craig Barnes

    24 de abril de 2019 a las 10:04

  • @CraigBarnes Efectivamente

    – Bilow

    25 de abril de 2019 a las 10:45

avatar de usuario
wbao

Desde esta artículo del foro:

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

fcntl(GETFL) es probablemente la operación más barata y menos probable que falle que puede realizar en un descriptor de archivo. En particular, la especificación sugiere que no puede ser interrumpido por señales, ni afectado por ningún tipo de bloqueo en cualquier lugar.

avatar de usuario
David Grayson

No creo que haya ninguna función que pueda decirle si el descriptor sigue siendo válido. El descriptor suele ser solo un pequeño número entero como 6 y su libc puede optar por reutilizar ese número si cierra el archivo y abre uno nuevo más tarde.

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

avatar de usuario
Juan Hascall

Me parece que si quiere saber si todavía apunta al mismo recurso, un enfoque (no perfecto) sería fstat() el descriptor justo después de abrirlo y luego puede volver a hacerlo y comparar los resultados. Comience mirando .st_mode& S_IFMT y partir de allí, ¿es un objeto del sistema de archivos? Mirar .st_dev / .st_ino. ¿Es un enchufe? Tratar getsockname(), getpeername(). No será 100% seguro, pero puede decirle si definitivamente no es lo mismo.

avatar de usuario
flotar

Resolví este problema para mí. ¡No sé si se puede usar para 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, consulte, por ejemplo, la página de manual http://linux.die.net/man/2/fstat

Saludos, Flo

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad