2013-06-27 22 views
8

场景:我有很多进程需要通过网络获取文件。如果该文件已经下载,我希望它在磁盘上缓存。如果另一个进程正在下载文件,则阻塞,直到完成下载。如何在Linux中以原子方式创建锁定的文件?

我一直在试图找到最简单的方法来做到这一点。最显而易见的方法是:

create file w/ an exclusive lock active on it only if it doesn't exist (O_CREAT | O_EXCL) 
if file exists already: 
    open file and acquire exclusive lock 
else: 
    download to newly created file 
release lock 

该系统在实现上述目标与(貌似)没有竞争条件

不幸的是,我无法找到如何使用open()等创建的文档在Linux中锁定的文件。如果我分裂创建踏进:

open w/ O_CREAT | O_EXCL 
flock 

的竞争条件,现在之间存在的创建和锁(非创建进程取得创作者不前的锁)。

我意识到我可以使用每个文件(例如文件名+'.lock),这是我尝试创建文件名之前获得的外部锁文件,但这感觉..不雅(我现在需要担心如何文件实际上有一个.lock后缀!)

是否有自动创建和锁定它(如Windows提供的)或者是外部lockfile方法几乎是标准/必需的?

回答

6

无论如何这场比赛依然存在。如果文件可能存在也可能不存在,那么在尝试锁定文件之前必须先测试它的存在。但如果文件是你的互斥体,那么你不可能做到这一点,“如果文件已经存在”(false)和“下载到新创建的文件”之间的空间是不受限制的。另一个过程可能会在您下载开始之前来到并创建该文件并开始下载,并且您会打开它。

基本上这里不使用fcntl锁,使用文件本身的存在。 open()与O_CREAT和O_EXCL将失败,如果该文件已经存在,告诉你其他人先到那里。

+0

我不知道我是否能以原子创建只有当文件不存在锁定的文件比赛将如何存在。 (条件也是原子)。 O_CREAT |如果文件不存在,则O_EXCL是一个原子创建;我只是想用锁来做到这一点。另一个进程无法开始下载,因为它会检测到文件存在。最后,我不能单独使用打开,因为我必须阻止直到下载完成;在我的解决方案中,我依赖(独占读/写)锁定。 – UsAaR33

+2

你是对的,自动创建和锁定文件将解决您的问题。但这不是fcntl锁定工作的方式,对不起。如果您想使用fcntl锁定,则在您的程序执行任何同步操作之前,您所锁定的文件必须存在。找到一种方法将if()中的创建移动到伪代码之外,或者处理另一个不使用下载文件作为互斥体的同步协议。 –

+0

明白了,所以答案是Linux不提供开放的Windows风格的原子锁。我会坚持使用lockfile方法。 – UsAaR33

0

为什么不使用lockfile工具?

例子

假设你要确保访问文件“重要”是 系列化,即不超过一个程序或shell脚本应 允许访问它。为了简单起见,我们假设它是一个shell脚本,它是 。在这种情况下,你可以解决这个问题是这样的:

... 
lockfile important.lock 
... 
access_"important"_to_your_hearts_content 
... 
rm -f important.lock 
... 
相关问题