Синхронизация доступа к файлу с flock в Stack Overflow

Я пытаюсь понять, как правильно синхронизировать чтение / запись файла, используя flock в 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. Однако содержимое файла test.txt очищается при выходе из testwrite.php. Дело в том, что fopen всегда успешен, даже если файл был заблокирован в другом процессе. Если файл открывается в режиме «w», содержимое файла будет удалено независимо от блокировки. Так какой смысл здесь? Это на самом деле ничего не защищает.

1

Решение

Ты используешь fopen() с w режим в testwrite.php, При использовании w вариант fopen() будет обрезать файл после его открытия. (увидеть fopen()).

Из-за этого файл усекается в вашем примере, прежде чем вы попытаетесь получить монопольную блокировку. Однако вам понадобится открытый файловый дескриптор, чтобы использовать flock(),

Выходом из этой дилеммы является использование файла блокировки, отличного от файла, над которым вы работаете. flock() страница руководства упоминает это:

Поскольку flock () требует указатель файла, вам, возможно, придется использовать специальный файл блокировки, чтобы защитить доступ к файлу, который вы собираетесь обрезать, открыв его в режиме записи (с аргументом «w» или «w +» для fopen () ).

0

Другие решения

Принятый ответ слишком сложен. Вы можете просто открыть файл, используя аргумент «c», который не усекает файл. Затем вызывайте ftruncate (), только если вы получили блокировку.

От документация:

‘c’ Открыть файл только для записи. Если файл не существует, он
создано. Если он существует, он не усекается (в отличие от ‘w’),
ни вызов этой функции не удался (как в случае с ‘x’).
указатель файла расположен в начале файла. Это может быть
полезно, если желательно получить консультативную блокировку (см. flock ()) перед
попытка изменить файл, так как использование ‘w’ может обрезать файл
до получения блокировки (если требуется усечение, ftruncate ()
может использоваться после запроса блокировки).

0

По вопросам рекламы [email protected]