2008-11-06 15 views

Respuesta

14

Si las bibliotecas están abriendo archivos que no conoce, ¿cómo sabe que no los necesitan después de un tenedor? Los identificadores no exportados son un detalle interno de la biblioteca. Si la biblioteca los quiere cerrar, registrará un controlador atfork() para cerrarlos. Caminar detrás de un fragmento de código cerrando sus manejadores de archivos detrás de su parte posterior conducirá a problemas sutiles difíciles de depurar ya que la biblioteca generará un error inesperado cuando intente trabajar con un manejador que sepa que se abrió correctamente, pero no se cerró.

0

Las bibliotecas razonables siempre tendrán funciones que liberan los recursos (por ejemplo, identificadores de archivos) que han asignado.

0

Solo un enlace, pero parece útil: How many open files? en netadmintools.com. Parece que usa las investigaciones de/proc para aprender sobre los archivos abiertos de un proceso, no está seguro si esa es la única manera o si hay una API. Analizar archivos para este tipo de información puede ser un poco ... desordenado. Además,/proc también podría estar obsoleto, algo para verificar.

16

En Linux puede consultar el directorio /proc/<pid>/fd - para cada fd abierto, habrá un archivo, denominado asa. Estoy casi seguro de que esta forma no es portátil.

Alternativamente puede usar lsof - disponible para Linux, AIX, FreeBSD y NetBSD, según man lsof.

1

Estoy de acuerdo con lo que otras personas han dicho sobre el cierre de archivos aleatorios que son peligrosos. Puede terminar archivando algunos informes de errores bastante interesantes para todas sus herramientas de terceros.

Dicho esto, si sabe no necesitará que esos archivos estén abiertos, siempre puede recorrer todos los descriptores de archivos válidos (1 a 65535, IIRC) y cerrar todo lo que no reconoce.

+0

Puede usar la llamada getdtablesize (2) para obtener el número de entradas en la tabla de descriptores de archivos del proceso. –

0

¿No es esto un problema de diseño? ¿Es posible que su proceso se bifurque antes de inicializar las bibliotecas que abren esos archivos?

2

Para empezar, no es necesario que se preocupe demasiado por los descriptores de archivos abiertos que desconoce. Si sabes que no vas a escribirles nuevamente, cerrarlos es una buena idea y no duele; acabas de hacer un tenedor() después de todo, los fds están abiertos dos veces. Pero del mismo modo, si los dejas abiertos, tampoco te molestarán; después de todo, no los conoces, es probable que no les escribas al azar.

En cuanto a lo que harán las librerías de terceros, es un poco sospechoso. Algunos probablemente no esperen encontrar una situación con un tenedor(), y podrían terminar escribiendo accidentalmente en el mismo fd de dos procesos sin ninguna sincronización. Otros probablemente no esperan que cierres sus fds sobre ellos. Tendrás que verificar Es por eso que es una mala idea abrir aleatoriamente un descriptor de archivo en una biblioteca y no darle a la persona que llama para que lo administre.

Dicho todo esto, en el espíritu de responder a la pregunta original, no hay una manera particularmente buena. Puede llamar al dup() o dup2() en un descriptor de archivo; si está cerrado, la llamada fallará con EBADF.Así que se puede decir:

int newfd = dup(oldfd); 
if (newfd > 0) 
{ 
    close(newfd); 
    close(oldfd); 
} 

pero en ese momento lo va igual de bien fuera diciendo close(oldfd) en primer lugar, y haciendo caso omiso de cualquier EBADFs.

Suponiendo que todavía desea tomar la opción nuclear de cerrar todo, necesita encontrar la cantidad máxima de descriptores de archivo abiertos posibles. Asumir 1 a 65,535 no es una buena idea. Primero que nada, los fds comienzan en 0, por supuesto, pero tampoco hay un límite superior definido. Para ser portátil, POSIX sysconf(_SC_OPEN_MAX) debe decirle, en cualquier sistema POSIX cuerdo, aunque estrictamente hablando es opcional. Si te sientes paranoico, comprueba el valor de retorno de -1, aunque en ese punto, en su mayoría, debes recurrir a un valor codificado de todos modos (1024 debería estar bien a menos que estés haciendo algo extremadamente extraño). O si está bien con ser específico de Linux, puede profundizar en/proc.

No olvides cerrar fds 0, 1 y 2, eso realmente puede confundir las cosas.

+0

Bueno, generalmente no te importa hasta que llegues al limo y empieces a recibir demasiados errores en los archivos abiertos. – philant

5

Como se mencionó en la respuesta de @Louis Gerbarg, las bibliotecas probablemente esperan que los manejadores de archivos se mantengan abiertos en fork() (que se supone que es, después de todo, una copia casi idéntica del proceso principal).

El problema que la mayoría de la gente tiene está en el exec() que a menudo sigue al fork(). Aquí, la solución correcta es para la biblioteca que creó los identificadores para marcarlos como close-on-exec (FD_CLOEXEC).

En las bibliotecas utilizadas por los programas multiproceso, existe una condición de carrera entre una biblioteca que crea un identificador de archivo y la configuración FD_CLOEXEC (otra cadena puede fork() entre ambas operaciones). Para solucionar ese problema, se introdujo O_CLOEXEC en el kernel de Linux.

14

Se puede hacer desde un shell:

lsof -P -n -p _PID_

Dónde PID es el PID del proceso.

+0

¿Cuál es el punto de hacerlo en el caparazón? ¿Cómo se supone que debo ingresar en el proceso de mi hijo bifurcado para cerrarlo? – sep

+1

@sep: esta respuesta quizás no sea la mejor cuando se considera la descripción de su problema, pero es seguro que aclara la pregunta real. Entonces, gracias Felipe por ayudarme a encontrar los mangos de mi proceso :) – Superole

Cuestiones relacionadas