Linux 上的 flock 与 lockf
- 2024-11-08 09:04:00
- admin 原创
- 174
问题描述:
如果lockf
使用 0 偏移量,那么在独占模式下使用时flock
和之间有何区别lockf
(如果有)?
我之所以问这个问题,是因为我正在阅读基于平台在这两个函数中有条件编译的代码,并且我想了解可能的原因。
解决方案 1:
flock()
和之间的实际区别lockf()
在于语义(关闭和传递方面的行为)、对 NFS 和其他共享文件系统的适用性,以及咨询锁是否对使用fcntl()
锁的其他进程可见。
您使用的库仅具有根据当前平台选择所需语义的逻辑。
如果语义(描述符传递、分叉等的行为)可以接受,则您应该更喜欢使用lockf()
/fcntl()
锁而不是flock()
Linux 中的锁,因为前者适用于 NFS 等文件系统,而后者则不适用。(在 BSD 和 Mac OS X 上,我认为您需要明确使用fcntl()
, 。)
在 Linux 中,lockf()
只是 的包装器fcntl()
,而flock()
锁是分开的(并且只适用于本地文件系统,而不能用于 2.6.12 之前的内核上的 NFS 安装)。也就是说,一个进程可以flock()
对文件拥有咨询排他锁,而另一个进程fcntl()
对同一个文件拥有咨询排他锁。两者都是咨询锁,但它们不会交互。
在Mac OS X和FreeBSD上,lockf()
//flock()
锁fcntl()
都相互交互,尽管建议开发人员在应用程序中仅使用其中一个接口。但是,只有fcntl()
锁在NFS 挂载上才有效(并且显然,只有当 NFS 客户端和服务器都配置为支持记录锁时,这种情况在例如 Web 托管环境中非常罕见;这对一些 Web(框架)开发人员来说是一个巨大的麻烦)。
POSIX 没有明确指定锁应该如何lockf()
交互,过去也存在分歧。现在,情况已经平静了一些,flock()
可以大致说fcntl()
fcntl()
锁是最可靠的
在所有架构中,它们最有可能在共享文件系统(例如 NFS 和 CIFS 挂载)上正常工作。
最常见的是,
lockf()
作为“简写”实现fcntl()
另一种选择是作为的“简写” flock()
,这是可能的,但现在很少见。
fcntl()
并且flock()
在继承和自动释放方面具有不同的语义
fcntl()
锁在 中保留exec()
,但不能在 中继承。当拥有该锁的进程关闭引用同一文件的任何fork()
描述符时,锁将被释放。
在 Linux、FreeBSD 和 MAC OS X 中,flock()
锁与打开的文件描述符耦合:传递描述符也会传递锁。(手册页指出“锁在文件上,而不是在文件描述符上”。这并不矛盾。它只是意味着锁适用于文件。它仍然与描述符耦合,这样复制描述符也会传递相同的锁。)因此,flock()
如果多个进程在调用后从发起者那里获得了描述符,则它们可能同时对同一个文件拥有相同的排他咨询锁flock()
。
文件锁定是一个令人惊讶的复杂问题。我个人通过简单地坚持fcntl()
锁定获得了最佳结果。fcntl()
与锁定相关的语义并不是最容易使用的,在某些情况下可能会令人恼火;只是我发现它产生了最好的结果——最可靠、最便携、最不令人惊讶的结果。
解决方案 2:
条件编译最可能的原因是这两个函数并非在每个平台上都可用。