在php中使用flock进行文件访问同步

时间:2015-02-21 06:36:07

标签: php file flock

我试图理解使用PHP中的flock同步文件读/写的正确方法。

我有两个php脚本。

testread.php:

<?
$fp=fopen("test.txt","r");
if (!flock($fp,LOCK_SH))
  echo "failed to lock\n";
else
  echo "lock ok\n";
while(true) sleep(1000);

?>

和testwrite.php:

<?
$fp=fopen("test.txt","w");
if (flock($fp,LOCK_EX|LOCK_NB))
{
  echo "acquired write lock\n";
}
else
{
  echo "failed to acquire write lock\n";
}
fclose($fp);
?>

现在我运行testread.php并让它挂在那里。然后我在另一个会话中运行testwrite.php。正如预期的那样,flock在testwrite.php中失败了。但是,当testwrite.php退出时,将清除文件test.txt的内容。事实是,即使文件已被锁定在另一个进程中,fopen也会成功。如果使用“w”模式打开文件,则无论锁定如何,文件内容都将被删除。那么羊群在这里有什么意义呢?它并没有真正保护任何东西。

2 个答案:

答案 0 :(得分:0)

您在fopen()中使用w模式testwrite.php。使用w选项时fopen()将在打开文件后截断文件。 (见fopen())。

因为在尝试获取独占锁之前,文件在您的示例中被截断。但是,您需要一个打开的文件描述符才能使用flock()

摆脱这种困境的方法是使用与您正在处理的文件不同的锁定文件。 flock()手册页提到了这一点:

  

因为flock()需要一个文件指针,你可能必须使用一个特殊的锁文件来保护对你想要截断的文件的访问,方法是在写模式下打开它(用&#34; w&#34;或者&#34; w +&#34; fopen()的参数)。

答案 1 :(得分:0)

接受的答案过于复杂。您只需使用“c”参数打开文件,该参数不会截断文件。只有在获得锁定时才调用ftruncate()。

来自documentation

  

'c'打开文件只写。如果该文件不存在,则为   创建。如果它存在,它既不被截断(而不是'w'),   也不会调用此函数失败(与'x'的情况一样)。该   文件指针位于文件的开头。这可能是   如果希望获得咨询锁(请参阅flock())之前有用   尝试修改文件,因为使用'w'可能会截断文件   在获得锁之前(如果需要截断,则为ftruncate()   可以在请求锁定后使用。)