flock — Блокировка файлов

flock

(PHP 3>= 3.0.7, PHP 4)

flock — переносимое «совещательное/advisory» блокирование файлов.

Описание

bool flock (int fp, int operation [, int &wouldblock])

PHP поддерживает перенос блокированных файлов advisory-способом (что означает, что все программы, выполняющие доступ, должны использовать тот же способ блокирования, или блокировка работать не будет).

flock() работает с fp, который обязан быть открытым указателем на файл.
operation имеет одно из следующих значений:

Для получения shared-блокировки (reader) установите в operation значение LOCK_SH (установите 1 в версиях до PHP 4.0.1).

Для получения исключительной/exclusive блокировки (writer) установите в operation значение LOCK_EX (установите 2 в версиях до PHP 4.0.1).

Для освобождения блокировки (shared или exclusive) установите в operation значение LOCK_UN (3 в версиях до PHP 4.0.1).

Если вы не хотите, чтобы flock() блокировала, добавьте LOCK_NB (4 в версиях до PHP 4.0.1) в operation.

flock() позволяет реализовать простую модель reader/writer, которая может использоваться на практически любой платформе (включая большинство клонов Unix и даже Windows). Необязательный третий аргумент устанавливается в TRUE, если блокировка возможна (EWOULDBLOCK errno condition).

flock() возвращает TRUE при успехе и FALSE при ошибке (например, когда блокировка не может быть получена).

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

flock() не будет работать в NFS и многих других сетевых файловых системах. См. в вашей документации по ОС детальную информацию.

В некоторых ОС flock() реализуется на уровне процесса. При использовании API многопоточного сервера типа ISAPI вы не сможете рассчитывать на flock() для защиты файлов относительно других PHP-скриптов, запущенных в параллельных потоках в том же самом экземпляре сервера!

flock() не поддерживается на старинных файловых системах вроде FAT и их клонах и, следовательно, всегда возвращает FALSE в такой среде (это также верно для пользователей Windows 98).

flock — игнорирует ли php file_get_contents блокировку файлов?

Я прочитал PHP страница справочника в функции ‘file_get_contents’, которая ничего не говорит о том, как ‘file_get_contents’ ведет себя в отношении блокировки файлов в php. Однако в разделе комментариев пользователь Крис предполагает, что

file_get_contents обычно не учитывает блокировку стека в PHP, т.е.
консультативная блокировка.

Вы можете обойти это с помощью дополнительного кода для запроса общей блокировки,
лайк…

который я проверил с успехом. Я также проверил, что хотя файл был заблокирован с flock() исключительно LOCK_EX можно было заставить другой процесс php читать файл через file_get_contents как комментарий предложил бы.

Тем не менее, и именно поэтому я прошу информацию, я прочитал веб-страницу под названием «Чтение заблокированных файлов в PHP» , который утверждал следующее в отношении file_get_contents и блокировка файлов.

Чтение заблокированного файла с помощью file_get_contents ()

Это один из худших способов чтения файла, пока он заблокирован и изменен, потому что:
— file_get_contents () вернет пустую строку (как в «»)
— filesize () вернет фактическое количество байтов, записанных в файл

Я это утверждение правильно? Я запускаю несколько тестов, блокирую файл исключительно и постоянно пишу в него, используя file_get_contents в другом процессе PHP, чтобы прочитать файл и не испытал поведение, как указано выше

file_get_contents () вернет пустую строку (как в «»)

Это правда в целом, что PHP file_get_contents ничего не заботит о консультативной блокировке файлов.
Кроме того, я правильно предполагаю, что утверждения, сделанные на веб-странице пустой строки, возвращаемой file_get_contents, являются пустыми «», имеют значение true, только если файл пустой или временно пустой (при изменении), но обычно не пустые (только для причина файла flock() ред)?

Решение

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

Но да, в этом отношении это правда, что file_get_contents не имеет встроенного способа получения блокировки чтения при чтении файла. Таким образом, обходной путь будет путь.

file_put_contents позволяет получить блокировку для записи, хотя.

Функция Flock

Функция Flock осуществляет портируемую консультативную блокировку файлов.
Функция Flock позволяет осуществить простую модель чтения/записи, которая может быть использована практически на любой платформе (включая большинство вариантов Unix и даже Windows).

В версиях PHP до 5.3.2 блокировка освобождалась также вызовом функции Fclose (которая также вызывается автоматически по завершении скрипта).

PHP поддерживает портируемый способ консультативной блокировки (advisory locking) полностью всего файла (что означает, что все программы, осуществляющие доступ к файлу, должны использовать один и тот же способ блокировки, иначе блокировка не будет работать). По умолчанию, данная функция будет ждать получения блокировки; это поведение можно изменить с помощью описанного ниже параметра LOCK_NB.

Параметр Handle являет собой указатель (resource) на файл, обычно создаваемый с помощью функции Fopen.

Параметр Operation может принимать следующие значения:

LOCK_SH для получения разделяемой блокировки (чтение).

LOCK_EX для получения эксклюзивной блокировки (запись).

LOCK_UN для снятия блокировки (разделяемой или эксклюзивной).

Также возможно добавить константу LOCK_NB в качестве битовой маски к любой из вышеуказанных операций, если вы не хотите ждать, пока функция Flock получит блокировку.

Необязательный параметр Wouldblock будет установлен в 1, если блокировка будет блокирующей (код ошибки EWOULDBLOCK).

Функция Flock возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
Пример использования:
В Windows функция Flock использует обязательную (mandatory) блокировку вместо консультативной. Обязательная блокировка также поддерживается на Linux и операционных системах, основанных на System V с помощью стандартного механизма, который предоставляет системный вызов fcntl(): т.е. искомый файл должен иметь установленный бит доступа setgid и неустановленный бит группового выполнения. Для корректной работы этой схемы в Linux, файловая система также должна быть смонтирована с опцией mand.

Из-за того, что функции Flock необходим указатель на файл, вам может понадобиться воспользоваться специальным запирающим файлом для того, чтобы ограничить доступ к файлу, который вы намерены очищать, путём его открытия в режиме записи (используя «w» или «w+» в качестве аргумента функции Fopen).

Присвоение другого значения аргументу Handle в последующем коде отменит существующую блокировку.

Функция Flock не поддерживается на старых файловых системах вроде FAT и ее производных, так что всегда будет возвращать FALSE в этом окружении.

Использование flock для гарантии запуска одной копии процесса

Иногда, используя планировщик запуска программ cron необходимо удостоверится, что предыдущий запуск скрипта был завершен. (Например архивация файлов должна происходить после окончании предыдущего ее запуска).
В операционных системах Linux для этого удобно использовать утилиту- flock.

Эта комманда запустит /root/myscript.sh и создаст lock-файл для данного процесса. Пока он активен, новый вызов данного скрипта не произойдет.
После завершения программы, блокировка файла снимается и процесс может быть снова запущен.
Параметр -w 600 определяет время ожидания комманды flock на освобождение lock-файла.
Для моментальной отмены выполнения процесса используйте параметр -w 0, для ожидания же бесконечно долгого времени параметр нужно опустить.

Наиболее подходящее место для lock-файла, папка/var/run, но для ее использования сначала потребуется создать файл и дать пользователю, исполняющему скрипт, права на его запись.

Как пользоваться flock()?

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

Представим себе, что есть разные программные потоки, одни из которых читают данные — «читатели», а другие их меняют — «писари». Ясно, что «читатель» должен дождаться пока операции записи завершатся. При этом несколько «читателей» не мешают друг другу.

Семафор

Чтобы блокировка работала, необходимо использовать один и тот же способ блокировки. Иными словами, flock() нужно вызывать как при чтении, так и при записи.

В случае с «семафорным» файлом код может выглядеть вот так:

Как заблокировать чтение файла другими копиями скрипта на время чтения текущей копией?

Как сделать блокировку на чтение файла в php во время чтения?
В разделяемой блокировке меня смущает слово «разделяемая».

Я делаю watchdog для демона на php.
Демон — это обычный бесконечный цикл с отключенным тайм-аутом.
Watchdog запускается при каждом запросе index.php пользователем.
daemon.php каждые 2 минуты записывает в файл daemon.active значение date(‘Ymdhi’).
А index.php проверяет значение daemon.active
таким выражением и выполняет
ping(‘http://’.$host.’/daemon.php’) , если выражение верно.
В htaccess запрещен доступ к daemon.php со всех IP, кроме localhost, чтоб избежать одновременного исполнения двух и более демонов.
Как сделать блокировку на чтение файла daemon.active, пока его читает index.php, чтоб daemon.php не вызвался несколько раз, если index.php запустится одновременно несколько раз.

  • Вопрос задан более трёх лет назад
  • 1147 просмотров

Вадим Егоров: В документации все описано.
«PHP поддерживает портируемый способ консультативной блокировки (adviosory locking) полностью всего файла (что означает, что все программы, осуществляющие доступ к файлу, должны использовать один и тот же способ блокировки, иначе блокировка не будет работать). По умолчанию, данная функция будет ждать получения блокировки; это поведение можно изменить с помощью описанного ниже параметра LOCK_NB.»

Леша Киселев: я пытался делать так:

index.php (на белом сервере; вызывает пользователь)

Вадим Егоров:
«оказывается ничего он не ждет, а просто выдает ошибку»

Из доки:
«Также возможно добавить константу LOCK_NB в качестве битовой маски к любой из вышеуказанных операций, если вы не хотите ждать пока flock() получит блокировку.»

Леша Киселев: что за бред??
вообще обьясняли что такое flock рукожопы какие-то
масло масленое

wouldblock
Необязательный третий параметр будет установлен в 1, если блокировка будет блокирующей (код ошибки EWOULDBLOCK). (не поддерживается на Windows)

Вадим Егоров: Да, сорян, проглядел. Очевидно, что вы хотите сделать эксклюзивную блокировку, что бы другой процесс не смог записать данные в файл. Соответсвенно, нужно блокировать файл на запись!

Вадим Егоров:
«LOCK_NB чтобы не ждать, пока будет получена блокировка (не поддерживается в Windows).» Внимание на инфу по винде.

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

14.2.3. Блокирование BSD: flock()

14.2.3. Блокирование BSD: flock()

4.2 BSD представило свой собственный механизм блокировки, flock() [155]. Функция объявлена следующим образом:

int flock(int fd, int operation);

Дескриптор fd представляет открытый файл. Имеются следующие операции:

LOCK_SH Создает совместную блокировку. Может быть несколько совместных блокировок.

LOCK_EX Создает исключительную блокировку. Может быть лишь одна такая блокировка.

LOCK_UN Удаляет предыдущую блокировку.

LOCK_NB При использовании побитового ИЛИ с LOCK_SH или LOCK_EX позволяет избежать блокирования функции, если блокировка файла невозможна.

По умолчанию запросы блокировки файла будут блокировать функцию (не давать ей вернуться), если существует конкурирующая блокировка. Запрашивающая функция возвращается, когда конкурирующая блокировка файла снимается и осуществляется запрошенная функцией блокировка файла. (Это предполагает, что по умолчанию имеется возможность возникновения тупика.) Чтобы попытаться заблокировать файл без блокирования функции, добавьте посредством побитового ИЛИ значение LOCK_NB к имеющемуся значению operation .

Отличительными моментами flock() являются следующие:

• Блокировка с помощью flock() является вспомогательной; программа, не использующая блокировку, может прийти и испортить без всяких сообщений об ошибках файл, заблокированный с помощью flock() .

• Блокируется весь файл. Нет механизма для блокировки только части файла.

• То, как был открыт файл, не влияет на тип блокировки, который может быть использован. (Сравните это с fcntl() , при использовании которой файл должен быть открыт для чтения для получения блокировки чтения, или для записи для блокировки записи.)

• Несколько открытых для одного и того же файла дескрипторов используют совместную блокировку. Для удаления блокировки может использоваться любой из них. В отличие от fcntl() , когда нет явного разблокирования, блокировка не удаляется до тех пор, пока не будут закрыты все открытые дескрипторы файла.

• Процесс может иметь лишь одну блокировку файла с помощью flock() ; последовательный вызов flock() с двумя различными типами блокировок изменяет тип блокировки на новый.

• На системах GNU/Linux блокировки flock() совершенно независимы от блокировок fcntl() . Многие коммерческие системы Unix реализуют flock() в виде «оболочки» поверх fcntl() , но их семантика различается.

Мы не рекомендуем использовать flock() в новых программах, поскольку ее семантика не такая гибкая и поскольку она не стандартизована POSIX. Поддержка ее в GNU/Linux осуществляется главным образом для обратной совместимости с программным обеспечением, написанным для старых систем BSD Unix.

ЗАМЕЧАНИЕ. Справочная страница GNU/Linux flock(2) предупреждает, что блокировки flock() не работают для смонтированных удаленных файлов. Блокировки fcntl() работают, при условии, что у вас достаточно новая версия Linux и сервер NFS поддерживает блокировки файлов

Блокировка файлов от записи на PHP

При частых обращениях к файлам (для чтения или записи) может возникнуть такая ситуация, когда один процесс осуществляет запись в файл, а второй в это же время считывает данные из файла. Еще хуже, если данные считываются из файла, обрабатываются и обратно записываются. Таким образом, если не ставить блокировку на файлы на время их обработки, может возникнуть ситуация, при которой данные будут одновременно обрабатываться несколькими и процессами и могут быть искажены или потеряны.

Для блокировки и разблокировки файлов мы рекомендуем Вам использовать стандартную функцию PHP flock() с флагами LOCK_EX и LOCK_UN. Флаг LOCK_EX используется для эксклюзивной блокировки файла (т.е. доступ к файлу будет доступен только процессу, поставившему блокировку), а LOCK_UN — для снятия блокировки с файла.

Чтобы было понятнее, давайте рассмотрим пример блокировки и разблокировки файла file.txt:

php
$fh = fopen ( «file.txt» , «a+» ); //открываем для чтения/записи
flock ( $fh , LOCK_EX ); //блокируем файл
fseek ( $fh , 0 ); //ставим указатель на начало файла
while (! feof ( $fh )) $line . = fread ( $fh , 2048 ); //считываем из файла

//здесь производим обработку считанных данных

ftruncate ( $fh , 0 ); //очищаем файл
fwrite ( $fh , $Res_$line ); //записываем в файл
flock ( $fh , LOCK_UN ); //снимаем блокировку
fclose ( $fh ); //закрываем файл
?>

В случае использования блокировки файлов, если один процесс еще не закончил работу с файлом, а второй пытается считать или записать данные в тот же самый файл, то ничего страшного не произойдет, т.к. второй процесс не начнет работу с файлом, пока первый не снимет блокировку. Таким образом, просто увеличится время выполнения второго процесса (на время ожидания снятия блокировки), зато Ваши данные теперь никуда не пропадут, что гораздо более важно.

Как видите, ничего сложного на самом деле в блокировке файлов нет, и на скорости работы сайта не сказывается. Подобная блокировка файлов используется и на нашем сайте для подсчета количества посетителей онлайн. Но с блокировкой файлов стоит обращаться осторожно, т.к. может возникнуть ситуация когда блокировка файла может быть по какой-либо причине не снята и тогда в файл невозможно будет что-либо записать.

flock

flock — Портируемое рекомендательное запирание файлов

Описание

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

flock() является обязательным под Windows.

flock() применяется к handle, который должен быть указателем на открытый файл. Параметр operation может принимать следующие значения:

  • Чтобы установить общее запирание (чтение), установите operation в значение LOCK_SH (или 1, в случае версии PHP ниже 4.0.1).
  • Чтобы установить эксклюзивное запирание (запись), установите operation в значение LOCK_EX (или 2, в случае версии PHP ниже 4.0.1).
  • Чтобы отпереть файл (после общего или эксклюзивного запирания), установите operation в значение LOCK_UN (или 3, в случае версии PHP ниже 4.0.1).
  • Если вы не хотите, чтобы flock() блокировал файл при запирании, добавьте LOCK_NB (или 4, при использовании версии PHP ниже 4.0.1) к параметру operation.

flock() позволяет вам реализовывать простую модель чтения/записи, которая может быть использована практически на любой платформе (включая большинство проивзодных от Unix платформ, и даже Windows). Необязательный третий аргумент устанавливается в TRUE, если запирание также блокирует (код ошибки EWOULDBLOCK). Блокировка снимается при помощи этой же функции fclose() (которая также автоматически вызывается при завершении выполнения скрипта).

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Пример #1 Пример использования функции flock()

= fopen ( «/tmp/lock.txt» , «w+» );

if ( flock ( $fp , LOCK_EX )) < // выполнить эксплюзивное запирание
fwrite ( $fp , «Что-нибудь пишем\n» );
flock ( $fp , LOCK_UN ); // отпираем файл
> else <
echo «Не могу запереть файл !» ;
>

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

flock() не будет работать на NFS и многих других сетевых файловых системах. Обратитесь к документации вашей операционной системы для получения дополнительной информации.

В некоторых операционных системах flock() реализован на уровне процессов. При использовании многопоточных серверных API, таких как ISAPI, вы не можете полагаться на flock() для защиты ваших файлов от дугих PHP-скриптов, которые работают в параллельном потоке на том же сервере!

flock() не поддерживается на старых файловых системах вроде FAT и его производных, так что всегда будет возвращать FALSE в этом окружении (это особенно касается пользователей Windows 98).

flock

(PHP 3>= 3.0.7, PHP 4)

flock — переносимое «совещательное/advisory» блокирование файлов.

Описание

bool flock (int fp, int operation [, int &wouldblock])

PHP поддерживает перенос блокированных файлов advisory-способом (что означает, что все программы, выполняющие доступ, должны использовать тот же способ блокирования, или блокировка работать не будет).

flock() работает с fp , который обязан быть открытым указателем на файл.
operation имеет одно из следующих значений:

Для получения shared-блокировки (reader) установите в operation значение LOCK_SH (установите 1 в версиях до PHP 4.0.1).

Для получения исключительной/exclusive блокировки (writer) установите в operation значение LOCK_EX (установите 2 в версиях до PHP 4.0.1).

Для освобождения блокировки (shared или exclusive) установите в operation значение LOCK_UN (3 в версиях до PHP 4.0.1).

Если вы не хотите, чтобы flock() блокировала, добавьте LOCK_NB (4 в версиях до PHP 4.0.1) в operation .

flock() позволяет реализовать простую модель reader/writer, которая может использоваться на практически любой платформе (включая большинство клонов Unix и даже Windows). Необязательный третий аргумент устанавливается в TRUE , если блокировка возможна (EWOULDBLOCK errno condition).

flock() возвращает TRUE при успехе и FALSE при ошибке (например, когда блокировка не может быть получена).

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

Предупреждение!

flock() не будет работать в NFS и многих других сетевых файловых системах. См. в вашей документации по ОС детальную информацию.

В некоторых ОС flock() реализуется на уровне процесса. При использовании API многопоточного сервера типа ISAPI вы не сможете рассчитывать на flock() для защиты файлов относительно других PHP-скриптов, запущенных в параллельных потоках в том же самом экземпляре сервера!

flock() не поддерживается на старинных файловых системах вроде FAT и их клонах и, следовательно, всегда возвращает FALSE в такой среде (это также верно для пользователей Windows 98).

Илон Маск рекомендует:  Шаблон сайта команда HTML, CSS, 1 страница
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
Предупреждение!