2013-07-30 130 views
5
gcc (GCC) 4.7.2 
c89 

是否可以检查文件是否已关闭?检查用fopen打开的文件是否已关闭

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

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

当我进入我的清理程序时,我不知道文件是处于打开还是关闭状态。所以如果我尝试做两次fclose(fd),它会堆积转储。

一些想法,我已经扔周围:

  1. 的状态加入到被打开或关闭的文件,然后检查状态,意味着对于这样一个简单的工作更多的工作。
  2. 不要做任何事情,因为操作系统将在程序结束时自动清理。
  3. 是否有访问功能,但只是检查模式。

提前许多感谢,

+0

添加状态(第一个选项)会添加竞争条件,除非在状态与文件同步时屏蔽Ctrl + C信号。 – Inspired

+4

为什么不能在关闭后将'fd' _(奇怪名称,btw)_设置为'NULL'? – VoidPointer

+0

它与libc(通常是Glibc,但可能是[musl-libc](http://musl-libc.org/)等)相关的更多于编译器。 –

回答

4

AFAIK,glibc没有提供验证FILE*变量的方法。

保持某种状态或只设置fdNULL的作品,但是你刚才关闭文件后,要小心,不要进入你的日常清理,但重置fd之前。当Ctrl + C向程序发送一个信号(SIGINT)时,您可以在文件关闭和fd被重置时阻止该信号。所以,你的fclose在主程序应该是这样的:

// 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); 

并在您的清理程序,你应该只检查fd

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

如果你的程序是多线程的,你应该使用pthread_sigmask代替。

就你而言,在清理程序中简单调用fcloseall()会容易得多。

至于你的问题中的第二个选项,关于无所事事 - 好吧,操作系统将清理你的程序的一切。那么唯一的缺点是,如果打开写入流,某些数据可能不会写入磁盘。但也许在Ctrl + C的情况下,它只是好的。

+0

什么是* AFAIK * btw? – 2013-07-30 08:20:48

+4

据我所知,AFAIK是'据我所知'的缩写:) :) – Inspired

+1

谢谢,我不知道 – 2013-07-30 10:05:20

1

可能是它帮你,只是一些建议:

你可以查看文件通过使用进程ID的进程中打开。

  1. pid_t getpid(void);,返回调用进程的进程ID。
  2. 接下来将此PID传递给pfiles命令。

二:

您可以拨打int fcloseall (void);程序结束前。

此功能使的进程打开的所有流被关闭, 连接到相应的文件被破坏。所有缓冲的数据 被写入并且任何缓冲的输入被丢弃。如果所有文件均已成功关闭,则fcloseall函数 会返回值0,如果检测到错误,则返回 EOF。

+0

在Linux上,您可以使用(并以编程方式检查)进程内部的'/ proc/self/fd /'和'/ proc/self/fdinfo /'目录,或者从/ proc/$ PID/fd /外。 '/ proc /'被'pfiles'访问 –

+0

@BasileStarynkevitch我读过手册'pfiles'命令read proc-filesystem –

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

然后将其添加到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; 

在此之前fcolse:

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

和之后设置fdOpen = 0 ;接近文件通常//SIGINT will not interrupt us now.

然后

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

所以我们做一些清洁工作,然后在sig_int退出程序。

+0

这里唯一的问题是当sig_int()在普通的'fclose'后被调用,但在'fdOpen = 0;'。 – Inspired

+0

@灵感是的,你说得对。 –

4

它让我感到你脑子里有点混乱。

文件处理程序,与fopenfclose使用,f...功能过程范围。即,它们在应用程序内有效(通常)。

打开文件时可能发生两件事:您成功与否。如果成功,您可能会独占使用文件或与其他进程共享。如果你失败了,也许另一个进程已经在使用文件。搜索_fsopen

当进程结束时,通常是或中断(与Ctrl+C一样),OS早晚释放与进程相关的资源。这适用于文件处理程序,内存,...

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

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