gcc (GCC) 4.7.2
c89

Es posible comprobar si un archivo ya ha cerrado?

He abierto un archivo con fopen() y cerrado con fclose(fd).

Este archivo se abre y se cierra durante la ejecución del programa. Sin embargo, el usuario puede cancelar el programa haciendo un ctrl-c.

Cuando voy a mi rutina de limpieza, no sé si el archivo está en una abierta o cerrada. Así que si intento hacer un fclose(fd) dos veces, volcado de pila.

Algunas ideas que me han estado lanzando a su alrededor:

  1. Agregar un estado para que el archivo sea abierto o cerrado, y, a continuación, compruebe que el estado, significa más trabajo para un trabajo sencillo.
  2. No hacer nada como el sistema operativo de limpieza automatially cuando el programa termina.
  3. Está allá, en el acceso a la función, pero que se comprueba el modo.

Muchas gracias de antemano,

La adición de un estado (la primera opción) habría que agregar una condición de carrera, a menos que usted máscara Ctrl+C de la señal, mientras que el estado está sincronizado con el archivo.
¿por qué no puede usted establecer fd (extraño nombre, por cierto) a NULL después de cerrar ?
Se relaciona más con la libc (a menudo Glibc, pero podría ser musl-libc etc…) que para el compilador.
Tener un estado var #defined como OPEN y CLOSE. Cuando usted llame a fopen en el código, establezca el estado como Current_State = OPEN; y cuando llame fclose en el código, establezca el estado como Current_State = CLOSE; y el uso que current_state variable como y cuando sea necesario.

OriginalEl autor ant2009 | 2013-07-30

5 Comentarios

  1. 6

    AFAIK, glibc no proporciona un método para validar un FILE* variable.

    Mantener algún tipo de estado o simplemente la creación de fd a NULL funciona, pero tienes que tener cuidado de no entrar en su rutina de limpieza justo después de cerrar el archivo, pero antes de restablecer fd. Como Ctrl+C envía una señal (SIGINT) a un programa, usted puede bloquear la señal, mientras que el archivo se ha cerrado y fd se restablece. Así, su fclose en el programa principal debe verse como:

    //1. Block SIGINT
    sigset_t old_mask, to_block;
    sigemptyset(&to_block);
    sigaddset(&to_block, SIGINT);
    sigprocmask(SIG_BLOCK, &to_block, &old_mask);
    
    //2. Close the file and reset fd
    fclose(fd);
    fd = NULL;
    
    //3. Restore signal handling
    sigprocmask(SIG_SETMASK, &old_mask, NULL);

    Y en su rutina de limpieza debe comprobar fd:

    if (fd != NULL) fclose(fd);

    Si su programa es multiproceso, usted debe utilizar pthread_sigmask lugar.

    En su caso, simple llamada de fcloseall() en la rutina de limpieza será mucho más fácil.

    Como por la segunda opción significa en tu pregunta, sobre que no hacer nada, bueno, el sistema operativo de limpieza de todo para su programa. A continuación, el único inconveniente es que si no se abrieron escribir arroyos, algunos datos pueden no escriben en el disco. Pero tal vez en el caso de Ctrl+C es simplemente aceptar.

    Cuál es la AFAIK por cierto?
    Hasta donde yo sé, AFAIK es una abreviatura de «yo sé»:)
    Gracias, yo no sabía

    OriginalEl autor Inspired

  2. 4

    Que las costuras para mí que hay un poco de confusión en su mente.

    Controladores de archivos, se utiliza con fopen, fclose, f... funciones son alcance del proceso. I. e., son válidos dentro de la aplicación (normalmente).

    Dos cosas pueden suceder cuando usted abre un archivo: éxito o no. Si usted tiene éxito, usted puede estar usando un archivo de forma exclusiva o compartida con otros procesos. Si no, tal vez otro proceso ya está utilizando el archivo. Búsqueda _fsopen.

    Cuando el proceso termina, normalmente o interrumpido (como con Ctrl+C), OS libera los recursos asociados con el proceso, más pronto o más tarde. Esto se aplica a los controladores de archivos, memoria, …

    Respecto a tu pregunta, si su aplicación final normalmente o con Ctrl+C, sin cerrar el archivo de controladores serán liberados por el sistema operativo.

    Cuando se inicia la aplicación, usted necesita para abrir el archivo de controladores que necesita. OS no mantenerlas abiertas para usted.

    OriginalEl autor LS_ᴅᴇᴠ

  3. 2

    Tengo un problema similar en una situación diferente (no condición de carrera). Así que esta solución abarca tanto la pregunta en el título y uno de ellos preguntó por ant.

    Cuando fclose(fd) se llama la interna fd->_fileno bajo nivel de I/O-descriptor de archivo se establece en -1 (u otro no válido unix descriptor de archivo). Por lo que se podría comprobar la utilización de fileno(fd)>=0 para comprobar si fd es todavía válido corriente (mi problema original).

    Cuando CTRL-C es presionado, el proceso recibe una señal de referencia como SIGINT y ejecuta el correspondiente manejador de señal (por ejemplo, una función predefinida). Uno nunca debe tratar de hacer todo lo que implique el estado del programa (excepto para atómica configurable variables, por ejemplo, banderas) en un manejador de señal, debido a que la señal puede llegar en cualquier situación, por lo que incluso mientras fclose(fd) se ejecuta en glibc (así fd->_fileno es undefined durante la ejecución del controlador). Debido a esto la forma canónica aquí es establecer un indicador de la activación de la parada y de retorno. El principal de la aplicación, a continuación, debe comprobar este indicador lo suficientemente a menudo, y, si se fija, limpia y salida.

    Este programa finaliza después de que CTRL-C es presionado, sin que conduce a cualquier fd limpiado por el sistema.

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    
    char interrupted=0;
    
    void exit_handler(int sig){
        interrupted=1;
    }
    
    int main(char** argc, int argv)
    {
        FILE *fd;
    
        signal(SIGINT, exit_handler);
        signal(SIGTERM, exit_handler);
    
        while(1){
            fd=fopen("filepath.file","w");
            char *tst_str="Test String";
            if(fwrite(tst_str,1,11,fd)!=11)
                printf("Writing Error occured\n");
    
            if (fileno(fd)>=0){
                printf("FD Closed. (1)\n");
                fclose(fd);
            }
            if (fileno(fd)>=0){
                printf("FD Closed. (2)\n");
                fclose(fd);
            }
            if(interrupted)
                exit(0);
        }
        printf("Done.");
    }

    OriginalEl autor msebas

  4. 1

    Puede ayudar a usted, algunas sugerencias:

    Puede comprobar el archivo abierto por el proceso mediante el proceso de identificación.

    1. pid_t getpid(void);, devolver el IDENTIFICADOR de proceso del proceso que hace la llamada.
    2. Paso siguiente de esta PID para pfiles comando.

    Segundo:

    Puede llamar int fcloseall (void); antes de que el programa termina.

    Esta función hace abrir todas las corrientes del proceso a ser cerrado y
    la conexión a los archivos correspondientes para ser roto
    . Todos los datos almacenados en búfer
    está escrito y cualquier búfer de entrada se descarta. El fcloseall función
    devuelve un valor de 0 si todos los archivos se han cerrado con éxito, y
    EOF si se ha detectado un error.

    En Linux puedes usar (y comprobar mediante programación) el /proc/self/fd/ y /proc/self/fdinfo/ directorios desde el interior del proceso, o /proc/$PID/fd/ etc desde el exterior. /proc/ se accede por pfiles
    Es que he leído en el manual de pfiles comando leer proc-sistema de ficheros

    OriginalEl autor Grijesh Chauhan

  5. 0
    int sig_int(int signo)
    {
        if(fdOpen)
           fclose(fd);
        abort();
    }

    A continuación, agregue esto a main:

    static volatile fdOpen = 0;
    static FILE *fd;//I guess
    if(signal(SIGINT,sig_int) == SIG_ERR)
        printf("signal(SIGINT) error\n");
    
    if((fd =fopen("your_file_name","flag_you_need")) != NULL)
        fdOpen = 1;

    Hacer esto antes de fcolse:

    sigset_t newmask,oldmask;
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);//BLOCK SIGINT

    Y establecer fdOpen = 0 ;después de cerrar el archivo, normalmente//SIGINT will not interrupt us now.

    Luego

    sigprocmask(SIG_SETMASK,&oldmask,NULL);//RESET signal mask

    Así que hacer algunos trabajos de limpieza y, a continuación, salir del programa en sig_int.

    El único problema aquí es que cuando sig_int() se llama después de la normal fclose, pero antes de fdOpen = 0;.
    Sí .estás en lo correcto.

    OriginalEl autor Lidong Guo

Dejar respuesta

Please enter your comment!
Please enter your name here