En Linux, uso este código para redirigir stdout y stderr en un archivo, como se muestra en el código, el archivo se abre con fopen (f) y se cierra con close (fd).
int fd; FILE *f; f = fopen("test.txt", "rb+"); fd = fileno(f); dup2(fd,STDOUT_FILENO); dup2(fd,STDERR_FILENO); close(fd);Mi pregunta es si la instrucción close(fd) cierra todos los descriptores de archivo, o ¿es necesario usar fclose(f) también?
La regla es cerrar el nivel más externo. Aquí, el objeto ARCHIVO al que apunta f contiene el identificador del archivo fd pero también datos internos como un posible búfer y varios punteros hacia él.
Cuando usa close(fd) , libera las estructuras del kernel relacionadas con el archivo, pero no se liberan todas las estructuras de datos proporcionadas por la biblioteca estándar. Por otro lado, fclose(f) cerrará internamente el identificador del archivo fd , pero también liberará todos los recursos asignados por fopen .
TL/DR: si usas fd= open(...); para abrir un archivo, debe usar close(fd); para cerrarlo, pero si usas f = fopen(...); , entonces deberías usar fclose(f); .
Los flujos C FILE* utilizan E/S almacenadas en búfer internamente. fclose() vacía este búfer y luego cierra el descriptor de archivo en el nivel del sistema operativo. Es posible que cerrar () una secuencia de ARCHIVO * no vacíe este búfer interno y puede perder datos. Entonces, para flujos C, siempre use funciones C fxxx().
Como ya se señaló en las otras respuestas, debe usar fclose(f); en lugar de close(fd); .
Mi pregunta es si la instrucción close(fd) cierra todos los descriptores de archivos [...]
No, no cerrará todos los descriptores de archivos. Los descriptores de archivo STDOUT_FILENO y STDERR_FILENO seguirán abiertos y ahora se referirán al archivo abierto test.txt . Sin embargo, estos descriptores de archivo probablemente no deberían cerrarse, ya que es una buena práctica de programación que STDOUT_FILENO y STDERR_FILENO sigan siendo válidos hasta el final del programa. El kernel los cerrará automáticamente al finalizar el proceso.