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检查进程打开的文件
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.");
}