fcntl,lockf,哪个更适合用于文件locking?

寻找有关文件locking的fcntllockf的 优缺点的信息。 例如哪个更适合用于便携性? 我目前正在编写一个Linux守护进程,并想知道哪个更适合用于强制执行互斥。

lockf和fcntl有什么区别:

在许多系统上, lockf()库例程只是fcntl()一个包装。 也就是说, lockf提供了fcntl所做function的一个子集。

资源

但在某些系统上, fcntllockf锁是完全独立的。

资源

由于它是依赖于实现的,请务必始终使用相同的约定。 所以要么始终使用lockf,要么始终使用fcntl。 他们很可能会互换,但使用同一个更安全。

你select哪一个并不重要。


关于强制性与咨询性locking的一些说明

locking在Unix / Linux是默认的咨询 ,意味着其他进程不需要遵循设置的locking规则。 因此,只要您的合作stream程也使用相同的约定,那么locking哪种方式并不重要。

Linux确实支持强制locking,但是只有当你的文件系统安装了选项,并设置了文件特殊属性。 您可以使用mount -o mand来挂载文件系统,并设置文件属性gx,g+s以启用强制locking,然后使用fcntllockf 。 有关强制locking如何工作的更多信息,请参阅此处 。

请注意,锁不是应用于单个文件,而是应用于inode。 这意味着2个指向相同文件数据的文件名将共享相同的locking状态。

另一方面,在Windows中,你可以主动地打开一个文件,这将阻止其他进程完全打开它。 即使他们想要。 也就是说,锁是强制性的。 Windows和文件锁也一样。 任何具有合适访问权限的打开文件句柄的进程都可以locking文件的一部分,而其他进程将无法访问该部分。


Linux中的强制锁如何工作:

关于强制locking,如果进程使用读locking来locking文件的区域,则允许其他进程读取但不写入该区域。 如果进程使用写入lockinglocking文件的区域,则其他进程不允许读取或写入文件。 当进程不被允许访问文件的部分时会发生什么,取决于你是否指定了O_NONBLOCK 。 如果设置了阻塞,它将等待执行操作。 如果没有设置阻塞,您将得到EAGAIN的错误代码。


NFS警告:

如果您在NFS挂载上使用locking命令,请小心。 行为是未定义的,并且实现差异很大,无论是仅使用本地锁还是支持远程locking。

这两个接口都是POSIX标准的一部分,现在大多数系统都可以使用这两个接口(我刚刚检查过Linux,FreeBSD,Mac OS X和Solaris)。 因此,select一个更适合您的要求和使用它。

有一点要注意:当一个进程使用fcntllocking一个文件而另一个使用lockflocking一个文件时,会发生什么情况? 在大多数系统中,这些是等价的操作(事实上,在Linux下,lockf是在fcntl之上实现的),但是POSIX说他们的交互是未指定的。 因此,如果您正在与使用两个接口之一的另一个进程进行互操作,请select相同的接口。

其他人写道,锁只是咨询:你负责检查一个地区是否被locking。 另外,如果你想要使用lockingfunction,不要使用stdio函数。

在这种情况下(即“ 编写Linux守护进程并想知道哪个更适合用于强制互斥 ”),您的主要关注点应该是:

  1. 将locking的文件是本地的,还是可以在NFS上?
    • 例如,用户可以欺骗你在NFS上创build和locking守护进程的pid文件吗?
  2. fork时,锁的行为如何,或者当守护进程终止时有极端的偏见,例如kill -9

在这两种情况下, flockfcntl命令的行为都不相同。

我的build议是使用fcntl 。 您可以参考Wikipedia上的文件locking文章,深入讨论两种解决scheme所涉及的问题:

flock和fcntl都有怪癖,偶尔也会让其他操作系统的程序员感到困惑。 networking文件系统(如NFS)上的群集锁是否工作取决于实现。 在BSD系统上,鸡群呼叫是成功的无操作。 在2.6.12之前的Linux上,对NFS文件的flock调用只能在本地执行。 内核2.6.12和更高版本使用POSIX字节范围锁实现对NFS文件的群集调用。 实现fcntl()/ POSIX锁的其他NFS客户端可以看到这些锁。 1应用新锁之前,锁升级和降级释放旧锁。 如果应用程序将独占锁降级到共享锁,而另一个应用程序被阻塞,等待独占锁,那么后一个应用程序将获得排它锁,并且第一个应用程序将被locking。 当该文件的任何文件描述符被该进程closures时,即使该文件描述符从未请求过锁,也会删除与给定进程的文件关联的所有fcntl锁。 而且,fcntl锁不会被subprocessinheritance。 对于调用可能访问文件的子例程库的应用程序而言,fcntlclosures语义特别麻烦。

我最近在使用fcntl和flock的时候遇到了一个问题,我觉得我应该在这里报告,因为search任何一个词都显示这个页面在两个顶端附近。

build议BSD锁,如上所述,是咨询 。 对于那些不了解OSX(达尔文)的人来说是BSD。 打开要写入的文件时,必须记住这一点。

要使用fcntl / flock,您必须先打开文件并获取其ID。 但是,如果你用“w”打开文件,文件将立即被清零 。 如果你的进程无法获得锁,因为这个文件正在其他地方使用,它很可能会返回,将文件保留为0kb。 现在有锁的进程现在会发现文件已经从其下面消失了,灾难性的结果通常会随之而来。

为了弥补这种情况,当使用文件locking时, 永远不要打开文件“w”,而是打开“a”来追加。 然后,如果成功获取locking,则可以安全地清除文件为“w”,即。 :

fseek(fileHandle,0,SEEK_SET); //移动到开始位置

ftruncate(fileno((FILE *)fileHandle),0); //清除它

这对我来说是一个不愉快的教训。

由于您只编写一个使用它进行互斥的守护进程,因此它们是相同的,毕竟,您的应用程序只需要与自身兼容。

与文件locking机制的诀窍是一致的 – 使用一个,坚持下去。 改变他们是一个坏主意。

我在这里假设文件系统将是本地文件系统 – 如果不是,则所有投注都closures,NFS /其他networking文件系统以不同程度的有效性处理locking(在某些情况下,无)