C 在应用程序退出之前删除所有文件

C 在应用程序退出之前删除所有文件,c,linux,C,Linux,我正在编写一些代码,这是一个工具的后端。此工具在固定目录中创建其所有输出。现在,假设在任何时候,一个客户端想要杀死它的所有应用程序,那么所有文件都应该被删除。因此,我使用系统命令(rm-rf)删除该目录,但打开的文件不会被删除,因此该目录也不会被删除。我怎样才能巧妙地做到这一点 一个选项似乎是使用一个表来维护所有打开的文件,并在目录上触发rm-rf之前将它们全部关闭。但是,这可能会降低整个应用程序的速度 我探索的另一个选项是使用lsof查找打开文件的列表,并在rm-rf之前将它们全部关闭 我的问

我正在编写一些代码,这是一个工具的后端。此工具在固定目录中创建其所有输出。现在,假设在任何时候,一个客户端想要杀死它的所有应用程序,那么所有文件都应该被删除。因此,我使用系统命令(
rm-rf
)删除该目录,但打开的文件不会被删除,因此该目录也不会被删除。我怎样才能巧妙地做到这一点

一个选项似乎是使用一个表来维护所有打开的文件,并在目录上触发
rm-rf
之前将它们全部关闭。但是,这可能会降低整个应用程序的速度

我探索的另一个选项是使用
lsof
查找打开文件的列表,并在
rm-rf
之前将它们全部关闭

我的问题的另一个限制是,我在一个进程中打开了几个不同的文件,其中一个文件正被另一个进程使用。使用上述方法,如果我关闭所有文件描述符并尝试删除目录,逻辑上不应该删除该目录,因为还有其他进程打开的文件


如果您有任何建议,我们将不胜感激。

为什么不将程序包装成脚本

e、 g

#/垃圾箱/垃圾箱
mkdir
/路径/到/程序
rm-fr

在*nix系统上运行该程序而不是直接运行程序,您可以通过掩码和系统调用捕获应用程序的终止信号。有关示例代码,请参见

要列出打开的文件,只需查看
/proc/**PID**/fd
。您将拥有与lsof相同的内容:

lr-x------ 1 user user 64 2012-02-09 08:40 0 -> /dev/null
l-wx------ 1 user user 64 2012-02-09 08:40 1 -> /home/user/.xsession-errors
lrwx------ 1 user user 64 2012-02-09 08:40 11 -> /etc/passwd
l-wx------ 1 user user 64 2012-02-09 08:40 2 -> /home/user/.xsession-errors
lrwx------ 1 user user 64 2012-02-09 08:40 3 -> socket:[15449]
lr-x------ 1 user user 64 2012-02-09 08:40 4 -> socket:[15450]
l-wx------ 1 user user 64 2012-02-09 08:40 5 -> pipe:[11740]
l-wx------ 1 user user 64 2012-02-09 08:40 6 -> socket:[15448]
lrwx------ 1 user user 64 2012-02-09 08:40 7 -> anon_inode:[eventfd]
lrwx------ 1 user user 64 2012-02-09 08:40 8 -> pipe:[11740]
lrwx------ 1 user user 64 2012-02-09 08:40 9 -> /dev/urandom

有了这个列表,您就可以在离开之前grep感兴趣的文件并在信号处理程序中通过fd关闭它们。

我认为使用脚本对您的实例来说是一个好主意,Coren的答案是准确的。也就是说,我看到程序只是通过大量的文件描述符循环来关闭它们。如果您的描述符超过了循环范围,则可能会出现错误,但如果您打算关闭所有描述符,则这类操作不应损害应用程序,前提是它们在该限制范围内:

for (int i = 0; i < 4096; i++) {
    close(i);
}
for(int i=0;i<4096;i++){
关闭(i);
}
为了在应用程序退出之前完成此操作,您可以设置一个信号处理程序,正如Coren所提到并链接的那样。如果使用信号和处理程序,请确保在信号处理程序中执行的操作尽可能少,即只设置一个标志并让程序执行清理


Edit:另外,StackOverflow上的另一篇文章给出了这两个示例(#3类似于Coren的,适用于Linux),但也有一些链接指向处理这些内容的实际源代码。你可能想看看

只有在某些进程打开了目录中的文件并且目录位于远程磁盘上时,才应该存在删除整个目录的问题。在这种情况下,删除打开的文件可能会导致重命名该文件,以便远程系统可以保持对该文件的引用。如果文件位于本地磁盘上,则维护对已删除文件的引用没有问题


当打开文件的进程终止时,操作系统将自动关闭文件。如果没有其他进程打开任何文件,那么删除目录应该没有问题(假设没有其他问题,例如文件权限)。因此,您只需确保在删除目录之前终止打开文件的进程。

从“fcloseall”手册页:

#define _GNU_SOURCE
/* See feature_test_macros(7) *
/#include <stdio.h>
int fcloseall(void);
定义GNU源
/*请参见功能测试宏(7)*
/#包括
int fcloseall(无效);

如果您确信所有文件都是在已知的临时目录中创建的,并且程序正常终止(通过调用
exit
或从
main
返回),那么假设您的应用程序使用“fopen”和friends:)

以及其他答案,这应该是可行的您可以使用注册一个清理函数,该函数将使用
opendir
readdir
收集所有文件名并删除它们,然后
rmdir
目录本身

我在我的文件中做了类似的事情,函数
do\u finalize\u melt
靠近第10390行

您还可以向
atexit
注册一个调用
system(“rm-rf/path/to/your/dir”)
的函数,或者甚至可以运行一个脚本,将另一个执行
rm-rf
的脚本排队给系统,或者只需使用
atexit(myexit\u处理程序)

void myexit_handler(void)
{
   FILE* batchf = popen("/usr/bin/batch", "w");
   /* get some sleep to be sure our process had time to exit */
   fprintf (batchf, "/bin/sleep 5\n"); 
   fprintf (batchf, "/bin/rm -rf %s\n", yourtempdir);
   pclose (batchf);
}
我假设
yourtempdir
中没有顽皮的字符(例如,没有空格、引号或反斜杠…)

Linux的语义是,当程序退出时,已打开但已删除的文件将被删除。如果这些是NFS文件(但是在网络上放置一个临时目录是一个错误,因为您希望它更快!),那么确实有一些
.NFS*
文件仍保留在NFS服务器上(您需要某种方法来删除它们,可能是通过
ssh

在应用程序退出之前,您不应该尝试删除目录,而应该在它退出之后,否则仍然打开的文件将不会被删除。

该函数可能会帮助您吗?这将创建一个临时文件,该文件在程序退出时自动删除(我认为
abort
可能会覆盖该文件)


如果这不起作用,请注意(至少在Linux上)可以在文件关闭之前删除它们。它们从目录列表中消失,但是任何打开该文件的程序仍然可以访问它。所有程序一关闭文件,它就永远消失了。在此之前,重新打开它们的唯一方法是查看
/proc//fd/
。这是flash插件用来增加抓取视频流难度的技巧。

使用getdtablesize,假设您不想关闭stdin、stdout、stderr:

for(i=3;i<getdtablesize(); i++)
     ckerr(close(i));
所以这纯粹是穷人的专利
for(i=3;i<getdtablesize(); i++)
     ckerr(close(i));
        SVr4, 4.4BSD (the getdtablesize() function first appeared in 4.2BSD). 
    It is not specified in POSIX.1-2001; portable applications should employ
 sysconf(_SC_OPEN_MAX) instead of this call.