如何在另一个进程完成后删除文件?

时间:2013-12-02 23:45:44

标签: c++ c linux ubuntu

我在内存中保存了要打开的数据。我在ubuntu上创建一个临时文件和fork xdg-open,以使用标准应用程序打开一个文件。我想在程序关闭后删除临时文件。问题是xdg-open本身会打开另一个进程并立即退出。因此,我不知道什么进程打开了文件。我试图获得flock的独占锁,并在等待20 srcs后尝试unlink文件(以确保其他进程首先打开文件),调用成功并且open程序只是关闭文件。我想等到程序关闭然后删除文件。有没有人知道如何做到这一点?

2 个答案:

答案 0 :(得分:1)

当xdg-open不依赖后缀时,可以使用

fd = open(filename, O_RDONLY|O_CLOEXEC);
unlink(filename);

system("xdg-open /proc/%u/fd/%u", getpid(), fd); /* pseudo-code! system is not printf() like! */

close(fd);

答案 1 :(得分:1)

您可以使用inotify (see man 7 inotify)或文件租约(see man 2 fcntl, Leases section)来检测其他进程何时打开和关闭文件(使用inotify),或者确定文件是否由其他进程打开(文件租约)

核心问题是xdg-open通常是检查环境(可能还有目标文件)的脚本,然后执行二进制文件(反过来可能检查目标文件并执行另一个二进制文件),有可能这里的一个或多个阶段分叉并立即退出,客户端进程继续链。

这意味着system()返回的时间点基本上无关紧要。目标文件可能已经或可能没有被最终的应用程序打开;我们只是不知道,也无法知道。

一种选择是创建一个单独的进程组( session ),并监视会话,只要进程组存在,就保持原始文件的存在。但是,假设xdg-open链中没有任何脚本或二进制文件创建自己的会话。 (我不知道他们是否这样做,有很多不同的实现 - 每个桌面环境都使用自己的二进制文件,xdg-open是它们周围的兼容性包装。)

实际上,这意味着使用fork()setsid()exec*()以及waitpid()waitid()将您的实施替换为system() ;具有短睡眠的循环中的最后一个,以检测进程组中何时没有进程。

另一种选择是执行命令,然后(将子进程分叉)等待一段特定时间 - 比如说,只要普通用户可以忍受等待文件开始加载;换句话说,几秒钟,然后开始检查文件是否仍在使用中。在不再使用该文件后,可以取消链接。

使用inotify(),您可以在执行xdg-open命令之前分配监视,然后监视打开和关闭。因为xdg-open可能会检查目标文件以选择应用程序,所以您不能假设第一次关闭是最终结束;您还需要等待上述特定时间段,以确保应用程序开放链已完成。 然后,如果关闭的次数与打开次数一样多,则可以取消链接文件。否则,您将等待剩余的关闭,并在最后一个文件之后取消链接。

使用file leases,方法稍微简单一些,但也更有限。您只能获取用户自己拥有的普通文件的文件租约。只有当文件未被任何进程(包括同一进程的其他描述符)打开以供写入时,才能获得读取租约。只有当文件根本没有被任何进程打开时(包括同一进程的其他文件描述符),才能获得写入租约。当您持有租约时,打开文件的任何其他进程(如果您持有写入租约)或尝试修改它(如果您持有读取或写入租约)将导致SIGIO信号(默认情况下,您可以将其更改为实时信号)以发送给租赁持有人。降级或释放租约最多/proc/sys/fs/lease-break-time秒,直到内核强行破坏它为止;在此期间,开启者/文件修饰符将在open() / truncate()来电时被屏蔽。

在执行xdg-open之前,您可以尝试获取文件的写入租约。如果成功,您知道这是唯一的打开文件描述符。调用xdg-open后,当文件打开(或由其中一个二进制文件检查)时,租约将被破坏;您可以在通话前简单地发布租约以避免麻烦。 一段时间从xdg-open执行后经过适当的秒数 - 人类等待应用程序开始打开文件的时间 - 你开始定期检查文件是否仍然被某些人打开通过尝试获得写入租约的其他过程。如果写入租约成功,并且从您开始xdg-open开始已经过了足够的时间,那么您就知道"人类用户"如果文件被打开,或者应用程序已经关闭文件,那么就会变得太沮丧了,因此文件可以取消链接。

以上所有内容都可以结合起来,让你变得偏执,但就个人而言,我认为模拟人类行为的方法最为强大。我个人可以轻松配置时间限制(并写入租约尝试间隔),分别为10秒和1秒默认值。

最后,如果资源使用是一个问题,那么我建议您编写一个单独的帮助程序二进制文件来为您管理。基本上,您运行xdg-open [OPTIONS] FILENAME而不是运行/usr/lib/myapp/open DELAY INTERVAL [OPTIONS] FILENAME/usr/lib/myapp/open二进制分叉并立即退出。子进程都执行xdg-open,并实现上述过程以等待文件可以取消链接。每个/usr/lib/myapp/open二进制文件只需要非常少的数据(最小的驻留集大小)和资源(它们大多数都处于休眠状态),所以即使在内存中有几十个数据库也不会在嵌入式内部显着消耗Linux机器。

如果有兴趣,我可以在这里添加/usr/lib/myapp/open的示例C实现。 (请告诉我三种方法中哪一种最有趣 - 进程组监控,inotify或文件租约。)