繁体   English   中英

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

[英]How can I delete a file after another process finishes with it?

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

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

您可以使用inotify (参见man 7 inotify或文件租约(参见man 2 fcntl ,Leases部分)来检测其他进程何时打开和关闭文件(使用inotify),或者确定文件是否被其他进程打开(文件租赁)。

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

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

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

在实践中,这意味着使用fork()setsid()exec*()waitpid()以及waitid()替换system()和您自己的实现; 具有短睡眠的循环中的最后一个,以检测进程组中何时没有更多进程。

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

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

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

在执行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或文件租约。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM