| |
ck() может произойти
либо в результате отказа блокировки, либо после того, как блокировка будет
установ-
лена — но не до того! Таким образом, когда мы наконец-то дождемся разрешения
Часть IV. Стандартные функции PHP 266
доступа к файлу и произойдет выход из цикла while, мы уже будем иметь исключи-
тельную блокировку, закрепленную за нашим файлом.
Пример счетчика
Давайте напоследок рассмотрим классический пример, когда без блокировки файла
не обойтись. Если вы уже имели некоторый опыт в Web-программировании, то вы,
наверное, уже догадываетесь, что речь пойдет о проблеме, возникающей при
написа-
нии сценария счетчика.
Итак, нам нужен сценарий, который бы при каждом своем запуске увеличивал число,
хранящееся в файле, и выводил его в браузер. Несложная, казалось бы, задача
сильно
осложняется тем, что при большой посещаемости сервера могут быть запущены сразу
несколько процессов-счетчиков, которые попытаются обратиться к одному и тому же
файлу. Если не принять мер, это приведет к тому, что счетчик рано или поздно
"об-
нулится".
Далее следует сценарий, использующий блокировку для предотвращения указанной
проблемы.
Листинг 15.4. Простейший текстовый счетчик
$f=fopen("counter.dat","a+");
flock($f,LOCK_EX); // Говорим, что дальше будем работать только мы
$count=fread($f,100); // Читаем значение, сохраненное в файле
@$count=$count+1; // Увеличиваем его на 1 (пустая строка = 0)
ftruncate($f,0); // Стираем файл
fwrite($f,$count); // Записываем новое значение
fflush($f); // Сбрасываем файловый буфер
flock($f,LOCK_UN); // Отключаемся от блокировки
fclose($f); // Закрываем файл
echo $count; // Печатаем величину счетчика
?>
Здесь мы применяем только исключительную блокировку, потому что каждый раз,
когда нам нужно вывести на экран счетчик, его также нужно и увеличить.
Глава 16
Работа с каталогами
С точки зрения операционной системы каталоги — это те же самые файлы, только со
специальным именем. То есть директорию можно представить себе как файл, в кото-
ром хранятся имена и местоположения других файлов и каталогов. Этим обеспечива-
ется традиционная древовидность организации файловой системы в различных ОС.
С каждым процессом (в частности, и с работающим сценарием) ассоциирован свой
так называемый текущий каталог. Все действия по работе с файлами и каталогами
осуществляются по умолчанию именно в ней. Например, если мы открываем файл,
указав только его имя, PHP будет искать этот файл именно в текущем каталоге.
Су-
ществуют также и функции, которые могут сделать текущим любой указанный ката-
лог.
Манипулирование каталогами
Вот несколько полезных функций для работы с каталогами.
bool mkdir(string $name, int $perms)
Создает каталог с именем $name и правами доступа $perms. Права доступа для
ката-
логов указываются точно так же, как и для файлов. Чаще всего значение $perms
ус-
танавливают равным 0770 (предваряющий ноль обязателен — он указывает PHP на
то, что это — восьмеричная константа, а не десятичное число). Например:
mkdir("my_directory",0755); // создает подкаталог в текущем каталоге
mkdir("/data"); // создает подкаталог data в корневом каталоге
В случае успеха функция возвращает true, иначе — false. Необходимо заметить,
что пользователь не может создать подкаталог в родительском каталоге, права на
запись в который у него отсутствуют. Здесь точно такая же ситуация, как и с
файла-
ми.
Вы, наверное, заметили, что атрибуты доступа 0770 означают "доступен для
чтения, записи и исполнения для владельца и его группы". Что означает атри-
бут исполнения, установленный для каталога? Может быть, он разрешает
пользователям запускать из него программы? А вот и нет. Право на "исполне-
Глава 16. Работа с каталогами 269
ние" показывает, что пользователь сможет просмотреть содержимое катало-
га. Конечно, все это специфично для операционных систем семейства Unix.
bool rmdir(string $name)
Удаляет каталог с именем $name. В случае успеха возвращает true, иначе — false.
Как всегда, действуют стандартные ограничения файловой системы на эту операцию.
bool chdir(string $path)
Сменяет текущий каталог на указанный. Если такого каталога не существует, воз-
вращает false. Параметр $path может определять и относительный путь, задаю-
щийся от текущего каталога. Вот несколько примеров:
chdir("/tmp/data");
|
|