NFS上的flock(2)与fcntl(2)


19

Perl 5.x文档指出,其flock(..)的实现将使用以下本机调用之一,从1开始,如果不可用,则朝3努力:

  1. 羊群(2)
  2. fcntl(2)
  3. 锁f(3)

没关系。但是,您可能已经注意到他们的免责声明,即不应在NFS上使用flock(2)。该文档建议使用-Ud_flock标志强制Perl使用flock(2)。flock(2)的手册页(在Redhat上)声明了有关NFS问题的类似免责声明。

我的问题是,为什么!?!?我似乎找不到更深入的文章,或者对WHY flock(2)的解释在NFS上并不安全。

我在Redhat(正在使用flock(2))和Solaris(正在使用fcntl(2))上用C和Perl编写了几个测试脚本。我运行strace / truss以确保Perl确实确实分别使用了flock(2)和fcntl(2)。我无法复制任何无法兑现锁的问题!是什么赋予了??

Answers:


3

Lennart Poettering最近对Linux文件系统锁定行为进行了一些研究,这并没有为锁定NFS描绘出特别乐观的画面(尤其是他在文章底部链接到的后续文章)。

http://0pointer.de/blog/projects/locking.html


1
那就是我一直在寻找的信息的确切类型。谢谢!经过几周的调查,我得出的解决方案非常相似,但是很高兴阅读一篇证实了我怀疑的文章(并提出了其他建议)。该页面评论的链接也是一个不错的参考,也是一篇有关POSIX及其历史的好文章):samba.org/samba/news/articles/low_point/tale_two_stds_os2.html
Jmoney38年

15

我很确定您正在研究遗留问题。回想一下,Perl5手册于1994年发布,它只是1991年对Perl4手册的编辑。在那些日子里,关于常被称为“噩梦文件系统”的人可能会说:“熊跳得不是很好。惊奇,但是它在跳舞”。

1991年时代的NFS2逐渐从Sun爬到其他平台,并且相对粗糙。安全模型实际上是不存在的(客户端计算机上的root可以读取NFS挂载的全部内容),并且通过nfs.lockd进行锁定是实验的这一方面。如果在两个不同的据称可互操作的实现之间根本不期望羊群语义正常工作,那将是愚蠢的。当时,同轴电缆是主要的以太网PHY,许多网络用户从未不喜欢使用它(这意味着您忘记戴上50Ω终端电阻了?),如果这样可以更好地控制内部网的状态。

拉里·沃尔(Larry Wall)和工作人员当时有充分的理由对NFS锁的正确性做出悲观的假设,这是一种防御性编程,将来的代码骑师不愿删除,因为很难证明是否存在缺陷。删除旧代码,这些代码在与您从未听说过的旧系统的互操作性中被重新引入。

从那时起,NFS有了很大的改进,并且lockd随时间迁移到了Linux 2.6内核的功能中。对于2003+系统的集合,可能可以信任NFS文件锁定,尤其是如果在跨应用程序运行的许多平台上对其应用程序进行了良好测试。

以上所有内容都是从记忆中剔除的,很可能可以通过研究得到证实(例如http://nfs.sourceforge.net/),但正如他们所说,证据就在锁定之中,如果您不对其进行测试, ,推测是坏了。


很好的分析。实际上,到目前为止,我已经得出了相同的结论。在发布该链接后,我再次阅读了nfs sourceforge页面,我终于找到了我想要的东西!这是直接从马口中进行的深入分析!
Jmoney10年

2
糟糕,我按Enter键...转到nfs.sourceforge.net,底部D10部分详细讨论了此问题。
Jmoney10年

3

另一个直接来自Linux-NFS常见问题解答:nfs.sf.net

我正在尝试使用flock()/ BSD锁来锁定多个客户端上使用的文件,但是这些文件已损坏。怎么来的?A. flock()/ BSD锁仅在2.6.12之前的Linux NFS客户端上本地起作用。使用fcntl()/ POSIX锁来确保文件锁对其他客户端可见。

以下是一些序列化对NFS文件的访问的方法。

使用fcntl()/ POSIX锁定API。这种锁定类型通过NLM协议或NFSv4在多个客户端之间提供字节范围锁定。使用一个单独的锁文件,并创建到它的硬链接。请参见creat(2)手册页的O_EXCL部分中的描述。值得注意的是,直到2.6早期的内核,O_EXCL才在Linux NFS客户端上创建。除非您运行的内核版本低于2.6.5,否则不要使用O_EXCL在多个NFS客户端之间创建并期望原子行为。

Perl默认使用flock()/ BSD锁定是一个已知问题。这可能会破坏从其他操作系统(例如Solaris)移植的程序,这些程序希望flock / BSD锁能够像POSIX锁一样工作。

在Linux上,使用文件锁定而不是硬链接具有将服务器的客户机缓存检查点确定为其他优点。获取文件锁后,客户端将刷新该文件的页面缓存,以便所有后续读取均从服务器获取新数据。释放文件锁后,对该客户端上文件的任何更改都将在释放该锁之前刷新回服务器,以便其他等待锁定该文件的客户端可以看到更改。

2.6.12中的NFS客户端通过根据POSIX字节范围锁模拟BSD样式锁来提供对NFS文件上的flock()/ BSD锁的支持。然后,使用相同仿真机制或使用fcntl()/ POSIX锁的其他NFS客户端将看到与Linux NFS客户端相同的锁。

在本地Linux文件系统上,POSIX锁和BSD锁彼此不可见。因此,由于这种模拟,无论客户端上的应用程序使用的是BSD样式还是POSIX-样式锁。如果服务器应用程序使用flock()BSD锁,它将看不到NFS客户端使用的锁。


那么,两个运行内核3.13。*的NFS客户端会看到彼此的flock()吗?
reinierpost

如果我理解正确,答案是否定的。除非我错过了一些东西,否则flock没有,也不会,并且不会在nfs挂载之间锁定。
丹尼尔·法瑞尔

至少在NFS4上如此。
rjh

3

现在已经过时了。NFS4支持在协议内部进行锁定(不需要lockd守护程序或RPC回调机制),Perl的flock()方法运行良好-我们在生产中使用了它。

内核的非常老的版本flock在NFS上实现为“无操作”(no-op),并且未正确支持诸如字节范围锁定之类的其他功能。这就是歇斯底里的来历。


非常感谢您的提示。使用NFS4挂载解决了我的问题。遵循access.redhat.com/documentation/en-us/red_hat_enterprise_linux/…来正确配置fstab。
maraspin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.