我的用例如下:我有一个程序强制在任何给定时间只能运行它的一个实例,所以在启动时它总是试图抓住标准位置的锁文件,并在文件终止时终止已被锁定.这一切都运行正常,但现在我想用一个新的命令行选项增强程序,当指定时,将导致程序打印出程序的状态报告然后终止(在主锁定保护之前)上面),其中包括锁文件是否已被锁定,正在运行的进程的pid是什么(如果存在),以及从数据库查询的某些程序状态.
正如您所看到的,当在“状态报告”模式下调用时,如果可用,我的程序实际上不应该获取锁.我只是想知道文件是否已经锁定,所以我可以通知用户状态报告的一部分.
从我的搜索,似乎没有任何方法这样做.相反,唯一可能的解决方案似乎是使用非阻塞标志调用flock(),然后,如果您实际获得了锁,则可以立即释放它.像这样的东西:
if (flock(fileno(lockFile),LOCK_EX|LOCK_NB ) == -1) { if (errno == EWOULDBLOCK) { printf("lock file is locked\n"); } else { // error } // end if } else { flock(fileno(lockFile),LOCK_UN ); printf("lock file is unlocked\n"); } // end if
我认为获取锁定并立即释放它并不是什么大问题,但我想知道是否有更好的解决方案,不涉及短暂和不必要的锁定获取?
注意:已经有几个类似的问题,其标题可能会使它看起来与这个问题完全相同,但从这些问题的内容可以清楚地看出,OP在获取锁定后有兴趣实际写入文件,所以这是一个截然不同的问题:
> Check if a file is already locked using flock()?
> How to check if a file is locked or not?
解决方法
你不能可靠地做到这一点.进程是异步的:当您无法获得锁定时,无法保证在您打印锁定状态时文件仍将被锁定.同样,如果你设法获得锁定,然后你立即释放它,所以当你打印解锁状态时,我的文件已被另一个进程锁定.如果有很多竞争者试图锁定此文件,则状态消息不同步的可能性很高.攻击者可以利用这种近似来穿透系统.
如果你依靠这个检查脚本来执行任何类型的并发工作,那么所有的赌注都会被取消.如果它只是产生信息状态,您应该在状态消息中使用过去时态:
if (flock(fileno(lockFile),LOCK_EX|LOCK_NB) == -1) { if (errno == EWOULDBLOCK) { printf("lock file was locked\n"); } else { // error } } else { flock(fileno(lockFile),LOCK_UN); printf("lock file was unlocked\n"); }