- •Пособие по работе в среде программирования php 4
- •1.Установка php
- •Настройка Apache для работы с php
- •Тестирование php
- •Установка дополнительных модулей
- •2. Характеристика языка php
- •Интерпретатор или компилятор?
- •Достоинства и недостатки интерпретатора
- •Использование php в Web
- •3. Переменные, константы, выражения
- •Переменные
- •Integer
- •Действия с переменными
- •1.Присвоение значения.
- •2.Проверка существования.
- •3.Уничтожение.
- •4.Определение типа переменной.
- •Константы
- •Выражения
- •Операции
- •4. Работа с данными формы
- •5. Конструкции языка
- •6. Ассоциативные массивы
- •Операции над массивами
- •1.Одинаковые ключи
- •2.Нулевой ключ
- •7. Функции и области видимости
- •8. Строковые функции
- •9. Работа с массивами
- •10. Математические функции
- •11. Работа с файлами
- •12. Работа с каталогами
- •13. Каналы и символические ссылки
13. Каналы и символические ссылки
Вообще-то, каналы и символические ссылки – совершенно разные вещи. Однако у меня есть по крайней мере два веских основания для того, чтобы сгруппировать их описания в одном месте.
●И то и другое сколько-нибудь результативно можно использовать лишь в системах на основе Unix, в других же операционных системах функции либо не реализованы, либо просто не работают.
●Примерно лишь один сценарий на PHP из тысячи может нуждаться в создании и использовании каналов и символических ссылок.
Каналы
Давайте начнем с каналов. Мы уже привыкли, что можем открыть какой-то файл для чтения при помощи fopen(), а затем читать или писать в него данные. Теперь представьте себе немного отвлеченную ситуацию: вы хотите из сценария запустить какуюто внешнюю программу (скажем, утилиту mail для отправки или приема почты). Вам нужен будет механизм, посредством которого вы могли бы передать этой утилите данные (например, E-mail и текст письма), а затем получить результат работы программы. Можно, конечно, заранее сохранить данные для запроса в отдельном временном файле, затем запустить программу, передав ей этот файл в параметрах и направив результат в другой файл, а затем считать его и таким образом решить задачу. Этот способ вполне приемлем (хотя и несколько медлителен), если вы используетеутилиту, которая работает не в режиме диалога (а только читает запрос и возвращает ответ). Однако, если после ответа программы-утилиты ей нужно будет послать какой-то другой запрос, не перезапускаясь, то задача становится на этом уровне неразрешимой. Как раз в такой ситуации и удобно использовать межпроцессные каналы. И вот как это работает.
// Запускаем процесс /bin/ls (параллельно работе сценария) в режиме
// чтения. Эта утилита Unix просто распечатывает содержимое текущего
// каталога, а ключ -l заставляет ее детализировать распечатку.
$fp=popen("/bin/ls -l","r");
// Теперь мы можем работать с $fp как с обычным файловым
// идентификатором. То есть выполнять функции чтения.
for($Lines=array(); !eof($fp);)
$Lines[]=fgets($fp,1000);
// Не забудем также закрыть канал.
pclose($fp);
Теперь более подробно. По команде popen() запускается указанная в первом параметре программа, причем выполняется она параллельно сценарию. Соответственно, управление сразу возвращается на следующую строку, и сценарий не ждет, пока завершится наша утилита (в отличие от функции system ()). Второй параметр задает режим работы: чтение или запись, точно так же, как это делается в функции fopen(). Хочу обратить ваше внимание на то, что каналнельзя открыть в режиме одновременного чтения и записи. Что послужило этому причиной? Ответ на поставленный вопрос в деталях занял бы слишком много места, чтобы поместиться в этой книге, но в двух словах можно сказать так: из-за буферизации ввода-вывода реально возникновение ситуации, когда процесс-родитель будет находиться в режиме ожидания данных от запущенного сына, а сын – будет ждать данные от родителя. Таким образом, возникает состояниевзаимной блокировки: оба процесса оказываются приостановлены. В общем случае эта проблема неразрешима, если у нас нет полного контроля над кодом процесса-сына.
Далее в нашем примере происходит вот что. Стандартный вывод утилиты (тот, который по умолчанию всегда является просто выводом на экран – да простят меня поклонники Unix, но все-таки так будет проще объяснить, не разъясняя, что такое перенаправление ввода-вывода и какую роль оно играет в этой ОС) прикрепляется к идентификатору $fp. Теперь все, что печатает утилита (а в нашем случае она печатает содержимое каталога), может быть прочитано при помощи обычных вызовов файловых функций чтения – fgets(), fread() и т. д. Программа ls не ждет никакого ввода (однако в общем случае это далеко не всегда так), вот почему мы пользуемся только серией вызовов fgets(). После того, как "дело сделано", канал $fp, вообще говоря, нужно закрыть. Если он ранее был открыт в режиме записи, утилите "на том конце" передается, что ввод данных "с клавиатуры" завершен, и она может закончить свою работу. В PHP не существует функций, которые могли бы открывать канал к дочернему процессу в режиме чтения и записи.