2012-02-09 88 views
3

我正在研究一些工具后端的代码。该工具在固定目录中创建其所有输出。现在假设客户想要终止其所有应用程序,那么应该删除所有文件。因此,我使用系统命令(rm -rf)删除目录,但打开的文件不会被删除,因此该目录也不会被删除。我该如何巧妙地做到这一点?删除应用程序退出前的所有文件

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

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

在我的问题上的一个额外的约束是,我已经打开一个进程中的几个不同的文件,其中一个被另一个进程使用。使用上述方法,如果关闭所有文件描述符并尝试删除该目录,则逻辑上它不应该被删除,因为仍有文件被另一个进程打开。

任何建议,将不胜感激。

+0

@all请帮我解决这个问题.... – 2012-02-14 18:56:07

+0

有谁能够告诉我OPEN_MAX =的sysconf(_SC_OPEN_MAX); 通过使用这个我得到的数字是从当前进程或系统中的所有进程打开文件描述符的数量。 – 2012-02-14 18:57:30

+0

一件事想我有一个进程打开了三个文件,其中一个被另一个进程打开,使用上述方法,如果我关闭所有FD并尝试删除该目录,在逻辑上是不应该,因为它仍然是由另一打开进程..请建议 – 2012-02-14 18:59:07

回答

0

我认为使用脚本对于您的实例来说是个好主意,Coren的答案很精确。话虽如此,我见过程序只是循环遍历大量的文件描述符来关闭所有的文件描述符。它有错误的可能性,如果你有比你遍历范围,但这样的事情不应该伤害,如果你打算关闭所有描述符的应用程序,只要它们是在这一限度内:

for (int i = 0; i < 4096; i++) { 
    close(i); 
} 

为了这个做你的应用程序退出之前,你可以设置一个信号处理器,提到和科伦联系。确保如果你使用的是你做的尽可能少的信号处理程序信号和处理程序,即只设置一个标志,让你的程序做了清理。

编辑:此外,this answer从StackOverflow的另一篇文章给出了如何做到这两个例子中这一点(#3是像科伦的,是Linux的),但也有几个是处理此链接到实际的源代码东东。你可能想看看!

+0

我不wanto包裹脚本我的代码,我也尝试使用您提到的相同方法,但问题是假设我有一个进程打开了三个文件,其中一个被另一个进程打开,用上述方法如果我关闭所有FD并尝试删除该目录,逻辑上它不应该,因为它仍然被另一个进程打开,但它会删除......这就是问题 – 2012-02-14 19:31:23

+0

@prp使用这些文件你的所有应用程序?如果是这样,为什么不在所有的程序中使用这种方法?最后一个应该最终删除与它一起的目录。 – 2012-02-14 19:34:33

3

为什么不将程序包装在脚本中?

例如

#!/bin/sh 

mkdir <some directory> 
/path/to/program <some directory to let the program know where to put stuff> 
rm -fr <the same directory> 

和运行,而不是运行的程序直接

+0

这将如何解决目前仍在打开的文件的问题,我想退出我的应用程序 – 2012-02-09 11:19:07

+3

的问题之前全部关闭说,要删除所有这些文件。当程序终止时,所有文件将被关闭并且控制权返回到脚本。脚本然后删除它们。 – 2012-02-09 11:20:54

1

在* nix系统这一点,你可以赶上带着面具和signal系统调用的应用程序的终止信号。有关示例代码,请参阅this question

为了列出打开的文件,你可以简单地看一看/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的信号处理程序关闭它们,只是在离开之前。

1

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

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

1

从“fcloseall”手册页:

#define _GNU_SOURCE 
/* See feature_test_macros(7) * 
/#include <stdio.h> 
int fcloseall(void); 

这应该假设你的应用程序使用“的fopen”和朋友:)

1

除了其他的答案,如果你是确保所有该文件是在一个已知的临时目录中创建,如果程序正常终止(通过调用exitmain返回)您可以使用atexit注册一个清理功能,它将使用opendirreaddir收集所有的文件名和删除他们,然后rmdir目录本身。

我在做类似的事情在我的gcc/melt-runtime.c文件,功能do_finalize_melt近线10390.

你也可以用一个atexit函数调用system("rm -rf /path/to/your/dir")甚至可能注册运行一个脚本这将排队的batch系统另一个脚本做rm -rf或只是打电话atexit(myexit_handler)

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有没有调皮字符内(即G。没有空格或引号或反斜杠...)

Linux语义是当程序退出时,已打开但已删除的文件将被删除。如果这些文件是NFS文件(但是在网络上放一个临时目录就是一个错误,因为你希望它很快!)然后确实有一些.nfs*文件保留在NFS服务器上(并且你需要一些方法来删除它们,也许通过ssh)。

你不应该试图之前删除目录应用程序退出,但只是后退出,否则仍然打开的文件将不会被删除里面。

0

tmpfile函数可能对您有帮助吗?这会创建一个在程序退出时自动删除的临时文件(我认为abort可能会覆盖此内容)。

如果这不起作用,请注意(至少在Linux上)可以在文件关闭之前删除文件。它们从目录列表中消失,但打开文件的任何程序都可以访问它。只要所有程序关闭文件,它都会消失。在此之前,重新打开它们的唯一方法是查看/proc/<pid>/fd/<num>。这是Flash插件使用它难以抓取视频流的技巧。

0

使用getdtablesize,假设你不希望关闭标准输入,标准输出,标准错误:

for(i=3;i<getdtablesize(); i++) 
    ckerr(close(i)); 

其中ckerr是一个错误检查功能。注意这符合旧标准:

 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. 

所以这纯粹是一个穷人的替代品....但它不被弃用,但。

考虑调用nftw()或FTW()来清理你的工作主任(IES),你可以执行删除()的回调函数。

相关问题