python lockf和flock行为

Jat*_*mar 9 python file-locking flock fcntl

我已经在stackoverflow上阅读了关于差异b/w的足够帖子,flock/lockf/fcntl但我无法回答以下观察:

>>> import fcntl
>>> a = open('/tmp/locktest', 'w')
>>> b = open('/tmp/locktest', 'w')
>>> fcntl.lockf(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>> fcntl.lockf(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>> fcntl.lockf(b, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>>
>>> a.close()
>>> b.close()

>>> a = open('/tmp/locktest', 'w')
>>> b = open('/tmp/locktest', 'w')
>>> fcntl.flock(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>> fcntl.flock(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>> fcntl.flock(b, fcntl.LOCK_EX | fcntl.LOCK_NB)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 35] Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)

为什么两种情况下的行为不同?我知道这两个不同的锁定机制的明显答案.我在寻找:

  1. 实际上lockf()或flock()对文件(inode/fd)的作用是什么?
  2. 根据演示,我们是否允许递归地使用相同的锁?

我理解基础知识fds和东西,所以我更愿意获得技术答案,更深入地了解操作系统级细节.

OSX 10.9.3,Python:2.7.5

小智 9

一篇关于此的好文章: 关于文件锁定的破碎性

简而言之:

  • POSIX锁:

    lockf()大部分时间只作为fcntl()的接口实现

    fcntl()锁绑定到进程,而不是文件描述符.如果进程具有针对特定文件的多个打开文件描述符,则用于获取锁定的这些文件描述符中的任何一个将重置锁.

  • BSD锁定:

    flock()锁绑定到文件描述符,而不是进程.

此外

对测试的一个很好的分析: 咨询文件锁定 - 我对POSIX和BSD锁的看法

摘要摘录:

  • fcntl和flock样式锁彼此完全正交.提供两者的任何系统(Linux都会)将独立处理通过它们中的每一个获得的锁.
  • 当进程退出或中止时,POSIX和BSD锁都会自动释放.
  • POSIX和BSD锁都在execve调用中保留,除非进程设置了FD_CLOEXEC标志,强制关闭文件描述符,而不是由新进程继承.

  • **tl; dr:****(A)**内存中锁(例如,[`multiprocessing` module](https://docs.python.org/3/library/multiprocessing.html#synchronization-between -processes)同步原语)比BSD和POSIX风格的锁更强烈,**(B)**BSD风格的`flock`锁比POSIX风格的`fcntl`锁更强,**(C )**除非要锁定的文件的权限严格限制在最多"0600",否则不应使用BSD-或POSIX-型锁. (4认同)
  • 公平的评估。应该强调的是,** POSIX锁在多线程情形下会静默失败**,并且(可以说*)应该被认为对现代软件堆栈有害– [GIL](https://wiki.python.org/moin/GlobalInterpreterLock )。更重要的是,应该强调的是:**组或世界可读文件上的POSIX和BSD锁都构成极大的安全风险。**为什么?因为拥有锁定文件读取权限的*任何*用户都可以通过先抢占该锁定然后再不释放它来永久锁定Python应用程序。 (3认同)