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