【问题标题】:File access synchronization with flock in phpphp中与flock的文件访问同步
【发布时间】:2015-04-22 22:56:32
【问题描述】:

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

我有两个 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”模式打开,文件内容将被删除而不管锁定。那么这里的羊群有什么意义呢?它并不能真正保护任何东西。

【问题讨论】:

  • flock 需要一个必须由 fopen 返回的文件句柄。

标签: php file flock


【解决方案1】:

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

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

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

因为flock() 需要一个文件指针,你可能必须使用一个特殊的锁定文件来保护对你打算通过以写模式打开它来截断的文件的访问(使用“w”或“w+”参数fopen())。

【讨论】:

  • 你不可能把fopen放在fopen之前。如果您不首先使用 fopen 获取有效的文件指针,则 $fp 甚至不是有效值。如何在 null 值上使用flock?
  • @StephenCheng 当然!!我怎么能忽略这一点?!..我需要AFK一段时间,但明天会有所帮助......
  • 我一开始就是这么怀疑的。我确实错过了文档页面上的注释行。感谢您指出。
【解决方案2】:

接受的答案过于复杂。您可以简单地使用“c”参数打开文件,它不会截断文件。然后只有在获得锁时才调用 ftruncate()。

来自documentation

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

【讨论】:

    猜你喜欢
    • 2012-02-28
    • 2013-05-23
    • 2010-09-16
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多