Главная / PHP статьи > PHP: блокировка доступа к файлу. Контроль доступа во время выполнения

PHP: блокировка доступа к файлу. Контроль доступа во время выполнения

Блокировка файлов с ожиданием

При осуществлении файловых операций нужно учитывать возможность их параллельного выполнения. С одним и тем же файлом могут взаимодействовать различные процессы. Одни выполняют чтение, а другие записывают данные. Некоторые задачи, решаемые в PHP, требуют явного контроля над таким поведением. Например, если в настоящий момент происходит запись в файл, нужно подождать его завершения перед началом чтения. Таким образом, пользователь будет получать актуальную информацию о содержимом.
PHP имеет встроенный механизм блокировки доступа к файлам. Он реализует консультативную модель (англ. advisory locking). Это означает, что все программы, работающие с файлом, должны реализовывать один и тот же способ проверки и использования блокировок. Иначе они не будут работать.
Блокировки доступа бывают двух типов: монопольная — другие процессы не могут записывать и читать данные пока не будет снята блокировка, совместная — все процессы могут читать, но не записывать.
Для блокировки файла используйте функцию flock(). В первом параметре она принимает дескриптор файла, а во втором указывается тип блокировки. Тип можно задать с помощью встроенных констант LOCK_SH(совместная) или LOCK_EX (монопольная). Функция возвращает true в случае захвата файла или false, если произошла ошибка. flock() также отвечает и за снятие блокировки. Для этого передайте ей дескриптор файла, а во втором параметре укажите константу LOCK_UN.
//если файл не существует создадим его в корне сайта
$filename = $_SERVER['DOCUMENT_ROOT']. '/test-file.txt';
if (!file_exists($filename)) {
    touch($filename);
}

//пытаемся получить контролируемый доступ к файлу
$descriptor = fopen($filename, 'w');
if (flock($descriptor, LOCK_EX)) {
    //формируем задержку разблокировки в 10 секунд
    sleep(10);
    flock($descriptor, LOCK_UN);
    echo 'Блокировка успешно снята!';
}


{reklama}

Проверка блокировки без задержки

Обратите внимание на пример, приведенный выше. Откройте два разных окна браузера и запустите PHP-скрипт на выполнение в каждом из них. В первом окне сразу появится надпись «Блокировка установлена!», а во втором – пройдет 15 секунд перед выводом аналогичного текста. Это происходит потому что flock() блокирует дальнейшее выполнение скрипта до момента получения контроля над файлом.
Если вы хотите продолжить выполнение без ожидания и вывести текст ошибки, ко второму параметру функции нужно подставить константу LOCK_NB с помощью битовой маски. Тогда flock() вернет результат сразу.
//если файл не существует создадим его в корне сайта
$filename = $_SERVER['DOCUMENT_ROOT']. '/test-file.txt';
if (!file_exists($filename)) {
    touch($filename);
}

//пытаемся получить контролируемый доступ к файлу
$descriptor = fopen($filename, 'w+');
if (flock($descriptor, LOCK_EX | LOCK_NB)) {
    //формируем задержку разблокировки в 10 секунд
    sleep(10);
    flock($descriptor, LOCK_UN);
    echo "Блокировка успешно снята!";

} else {
    echo 'Невозможно установить блокировку';
}
Отметим, что PHP реализует встроенные механизмы буферизации данных, предназначенных для записи в файл. Это необходимо для уменьшения количества операций с диском. Может случится так, что блокировка будет снята до того, как данные будут реально записаны в файл. Этот процесс контролируется вызовом функции fflush(), которая сбрасывает буфер файла и применяет все его изменения. Функция принимает всего один параметр — дескриптор файла, а возвращает результат логического типа.
Заметка!
В PHP блокировка файлов средствами вышеописанной функции не будет работать на старых файловых системах, сетевых дисках и в старых операционных системах Windows. На самом деле потребность блокировки файла может указывать на ошибки архитектуры приложения.
Возможно данные, к которым вы пытаетесь организовать контролируемый доступ, должны храниться с помощью систем управления базами данных: MySQL, PostgreSQL, SQLite и т.д.
30-04-2018, 21:19. Разместил: administrator
Вернуться назад