![](/img/trans.png)
[英]How can I delete data from a sequential file while it is being appended by another process
[英]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.