查找有关 fcntl 和 lockf的优势和缺点的信息 用于文件锁定。例如哪个更适合携带?我目前正在编写一个Linux守护程序,并想知道哪个更适合用于强制执行互斥。
答案 0 :(得分:61)
lockf和fcntl有什么区别:
在许多系统上,lockf()
库例程只是fcntl()
的包装器。也就是说lockf
提供了fcntl
所做功能的一部分。
但在某些系统上,fcntl
和lockf
锁是完全独立的。
由于它是依赖于实现的,因此请确保始终使用相同的约定。因此,要么始终使用来自两个进程的lockf,要么始终使用fcntl。它们很可能是可以互换的,但使用同一个更安全。
你选择哪一个并不重要。
关于强制性与咨询性锁定的一些注意事项:
默认情况下,在unix / linux中锁定建议,这意味着其他进程不需要遵循设置的锁定规则。因此,只要您的合作流程也使用相同的约定,您锁定的方式无关紧要。
Linux确实支持强制锁定,但前提是您的文件系统在安装了选项并且设置了文件特殊属性的情况下。您可以使用mount -o mand
挂载文件系统并设置文件属性g-x,g+s
以启用强制锁定,然后使用fcntl
或lockf
。有关强制锁定工作方式的详细信息,请参阅here。
请注意,锁不是应用于单个文件,而是应用于inode。这意味着指向相同文件数据的2个文件名将共享相同的锁定状态。
另一方面,在Windows中,您可以主动独占打开文件,这将阻止其他进程完全打开它。即使他们想要。即,锁是必需的。 Windows和文件锁也是如此。具有适当访问权限的打开文件句柄的任何进程都可以锁定文件的一部分,其他进程也无法访问该部分。
强制锁在Linux中的工作方式:
关于强制锁定,如果进程使用读锁定锁定文件的某个区域,则允许其他进程读取但不写入该区域。如果进程使用写锁定锁定文件的某个区域,则不允许其他进程读取或写入该文件。当不允许进程访问文件的部分时会发生什么情况取决于您是否指定了O_NONBLOCK
。如果设置了阻塞,它将等待执行操作。如果未设置阻止,则会收到错误代码EAGAIN
。
NFS警告:
如果在NFS安装上使用锁定命令,请小心。行为未定义,无论是仅使用本地锁还是支持远程锁定,实现都会有很大差异。
答案 1 :(得分:10)
这两个接口都是POSIX标准的一部分,现在大多数系统都可以使用这两个接口(我刚刚检查过Linux,FreeBSD,Mac OS X和Solaris)。因此,请选择更符合您要求的产品并使用它。
提醒一句:未指定当一个进程使用fcntl锁定文件而另一个进程使用lockf锁定文件时会发生什么。在大多数系统中,这些是等效的操作(实际上Linux lockf是在fcntl之上实现的),但POSIX表示他们的交互是未指定的。因此,如果您与使用两个接口之一的另一个进程进行互操作,请选择相同的接口。
其他人写过锁只是建议性的:你负责检查区域是否被锁定。另外,如果您想使用锁定功能,请不要使用stdio函数。
答案 2 :(得分:9)
在这种情况下(例如,“编写Linux守护程序并且想知道哪个更适合使用强制执行互斥”),您的主要关注点应该是:
fork
时,或者当守护进程以极端偏见终止时,锁将如何表现? kill -9
? flock
和fcntl
命令在两种情况下的行为都不同。
我的建议是使用fcntl
。您可以参考File locking article on Wikipedia深入讨论两种解决方案所涉及的问题:
flock和fcntl都有怪癖 偶尔会有来自的程序员 其他操作系统。是否涌入 锁在网络文件系统上工作, 比如NFS,就是实现 依赖。在BSD系统上,flock调用 是成功的无操作。在Linux之前 到2.6.12 flock对NFS文件的调用 只会在当地行动。内核2.6.12 以上实现了对NFS的flock调用 使用POSIX字节范围锁的文件。 其他人可以看到这些锁 实现的NFS客户端 fcntl()/ POSIX lock。1锁定升级 并降级释放旧锁 在应用新锁之前。如果 申请降级专属 另一个锁定共享锁 应用程序被阻止等待 独占锁,后一种应用 将获得独家锁和 第一个申请将被锁定。 与文件关联的所有fcntl锁 对于给定的进程,删除时 该文件的任何文件描述符都是 由该过程关闭,即使锁定 从来没有要求该文件 描述。另外,fcntl锁不是 由子进程继承。该 fcntl特别是关闭语义 对于那些应用来说很麻烦 调用可能的子程序库 访问文件。
答案 3 :(得分:7)
我最近在使用fcntl和flock时发现了一个问题,我觉得我应该在这里报告,因为搜索任何一个术语都显示这个页面接近顶部。
如上所述,建议BSD锁定是建议。对于那些不了解OSX(达尔文)的人来说是BSD。打开要写入的文件时必须记住这一点。
要使用fcntl / flock,您必须先打开文件并获取其ID。但是,如果您使用" w"打开文件该文件将立即清零。如果您的进程在其他地方使用该文件时无法获得锁定,则很可能会返回,将文件保留为0kb。具有锁定的进程现在会发现文件已从其下方消失,通常会出现灾难性后果。
为了解决这种情况,在使用文件锁定时,从不打开文件" w",而是打开它" a",追加。然后,如果成功获取锁定,则可以安全地将文件清除为" w"会有,即。 :
fseek(fileHandle,0,SEEK_SET); //移至开头
ftruncate(fileno((FILE *)fileHandle),0); //清除它
这对我来说是一个不愉快的教训。
答案 4 :(得分:1)
由于您只编写一个使用它进行互斥的守护程序,它们是等效的,毕竟,您的应用程序只需要与自身兼容。
文件锁定机制的诀窍是保持一致 - 使用一个并坚持下去。改变它们是一个坏主意。
我在这里假设文件系统将是本地文件系统 - 如果不是,则所有投注都关闭,NFS /其他网络文件系统处理具有不同程度有效性的锁定(在某些情况下没有)