Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 检查使用fopen打开的文件是否已关闭_C_Fopen_Fclose - Fatal编程技术网

C 检查使用fopen打开的文件是否已关闭

C 检查使用fopen打开的文件是否已关闭,c,fopen,fclose,C,Fopen,Fclose,是否可以检查文件是否已关闭 我使用fopen()打开了一个文件,并使用fclose(fd)关闭了一个文件 该文件在程序运行期间打开和关闭。但是,用户可以通过执行ctrl-c来终止程序 当我执行清理例程时,我不知道文件是处于打开状态还是关闭状态。因此,如果我尝试执行两次fclose(fd),它将堆栈转储 我提出了一些想法: 将状态添加到文件中,使其处于打开或关闭状态,然后检查该状态,这意味着对于这样一个简单的作业,需要进行更多的工作 不要做任何事情,因为当程序结束时,操作系统会自动清理 是否有访问

是否可以检查文件是否已关闭

我使用
fopen()
打开了一个文件,并使用
fclose(fd)
关闭了一个文件

该文件在程序运行期间打开和关闭。但是,用户可以通过执行
ctrl-c
来终止程序

当我执行清理例程时,我不知道文件是处于打开状态还是关闭状态。因此,如果我尝试执行两次
fclose(fd)
,它将堆栈转储

我提出了一些想法:

  • 将状态添加到文件中,使其处于打开或关闭状态,然后检查该状态,这意味着对于这样一个简单的作业,需要进行更多的工作
  • 不要做任何事情,因为当程序结束时,操作系统会自动清理
  • 是否有访问功能,但这只是检查模式

  • 提前非常感谢,

    可能会对您有所帮助,只是一些建议:

    您可以使用进程id检查进程打开的文件

  • ,返回调用进程的进程ID
  • 接下来将此PID传递给命令
  • 第二:

    您可以在程序终止之前调用

    此函数导致流程的所有开放流关闭并关闭 与要断开的相应文件的连接。所有缓冲数据 写入,并丢弃任何缓冲输入。fcloseall函数 如果成功关闭所有文件,则返回值0,并且 如果检测到错误,则为EOF

    然后将其添加到
    main

    int sig_int(int signo)
    {
        if(fdOpen)
           fclose(fd);
        abort();
    }
    
    在fcolse之前执行此操作:

    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;
    
    并设置
    fdOpen=0在您正常关闭文件后
    //SIGINT现在不会打断我们。

    然后


    所以我们做了一些干净的工作,然后在
    sig\u int
    退出程序

    AFAIK,glibc不提供验证
    文件*
    变量的方法

    保持某种状态或只是将
    fd
    设置为
    NULL
    是可行的,但您必须小心不要在关闭文件之后,而在重置
    fd
    之前进入清理例程。当Ctrl+C向程序发送信号(SIGINT)时,您可以在关闭文件和重置fd时阻止该信号。因此,主程序中的
    fclose
    应该如下所示:

    sigprocmask(SIG_SETMASK,&oldmask,NULL);//RESET signal mask
    
    在您的清理程序中,您只需检查
    fd

    // 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);
    
    如果您的程序是多线程的,则应改用
    pthread\u sigmask

    在您的情况下,在清理例程中简单调用
    fcloseall()
    会容易得多


    至于你问题中的第二个选项,什么都不做——好吧,操作系统会为你的程序清理一切。那个么唯一的缺点是,若有打开的写流,一些数据可能不会写入磁盘。但是,在Ctrl+C的情况下,可能没什么问题。

    我觉得你的脑子里有点混乱

    文件处理程序,与
    fopen
    fclose
    f..一起使用。
    函数是进程范围。即,它们在应用程序内有效(通常)

    打开文件时可能会发生两件事:成功与否。如果成功,则可能以独占方式使用文件或与其他进程共享文件。如果失败,可能另一个进程已经在使用文件。搜索
    \u fsopen

    当进程正常结束或中断时(如使用
    Ctrl+C
    ),操作系统迟早会释放与进程相关的资源。这适用于文件处理程序、内存等

    关于您的问题,无论您的应用程序是正常结束还是使用
    Ctrl+C
    ,未关闭的文件处理程序都将由操作系统释放


    每当应用程序启动时,都需要打开所需的文件处理程序。操作系统不会让它们为您打开。

    我在不同的情况下遇到了类似的问题(没有竞争条件)。所以这个解决方案涵盖了标题中的问题和ant提出的问题

    调用
    fclose(fd)
    时,内部
    fd->\u fileno
    低级I/O文件描述符设置为-1(或其他无效的unix文件描述符)。因此可以使用
    fileno(fd)>=0检查
    fd
    是否仍然是有效流(我的原始问题)

    当按下
    CTRL-C
    时,进程将接收一个被判定为
    SIGINT
    的信号,并执行相应的信号处理程序(例如预定义函数)。任何人都不应该尝试在信号处理程序中执行任何涉及程序状态的操作(原子可设置变量除外,例如标志),因为信号可能在任何情况下到达,因此即使在glibc中执行
    fclose(fd)
    (因此
    fd->\u fileno
    在处理程序执行期间未定义)。因此,这里的标准方法是设置一个触发关闭和返回的标志。然后,主应用程序需要经常检查该标志,如果设置了,则清除并退出

    此程序在按下
    CTRL-C
    后结束,不会导致系统清除任何fd

    if (fd != NULL) fclose(fd);
    
    #包括
    #包括
    #包括
    char=0;
    无效退出处理程序(int sig){
    中断=1;
    }
    int main(字符**argc,int argv)
    {
    文件*fd;
    信号(SIGINT,退出处理器);
    信号(SIGTERM,退出处理器);
    而(1){
    fd=fopen(“filepath.file”,“w”);
    char*tst_str=“测试字符串”;
    如果(写入(tst_街,1,11,fd)!=11)
    printf(“发生写入错误\n”);
    如果(文件号(fd)>=0){
    printf(“FD关闭。(1)\n”);
    fclose(fd);
    }
    如果(文件号(fd)>=0){
    printf(“FD关闭。(2)\n”);
    fclose(fd);
    }
    如果(中断)
    出口(0);
    }
    printf(“完成”);
    }
    
    添加状态(第一个选项)将添加竞争条件,除非在状态与文件同步时屏蔽Ctrl+C信号。为什么不能将
    fd
    (奇怪的名称,顺便说一句)设置为// 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);
    if (fd != NULL) fclose(fd);
    
    #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.");
    }