Как PHP выводит «Hello World»? — Взгляд за кулисы.

Это перевод с английского замечательной статьи Abhinav Singh.

Вам когда-нибудь было любопытно, как же PHP выводит для вас в браузере фразу “Hello World” с помощью echo? Например, у меня не было интереса, пока я не прочёл о внутренностях PHP и его расширениях. Мне подумалось, что, может, некоторым из вас будет занимательно открыть для себя другую сторону PHP, так что приступим. Здесь я коротко освещу тему «Как PHP штампует контент, запрошенный на веб-странице».

Общее описание

Вот что происходит по шагам:

  1. Мы никогда сами не запускаем PHP-демонов или что-то в этом роде. Когда мы запускаем Apache, то он также запускает PHP-интерпретатор (автор рассматривает среду с веб-сервером Apache, но многие вещи справедливы и для других конфигураций — прим. пер.).
  2. PHP связан с Apache (SAPI, серверным API) посредством модуля mod_php5.so.
  3. PHP в целом состоит из трех модулей (ядро PHP, движок Zend и уровень расширений).
  4. Ядро PHP — это модуль, который обрабатывает запросы, файловые потоки, имеет дело с ошибками и т.п.
  5. Движок Zend (ZE) преобразует человекочитаемый код в понятные машине лексемы/коды операций (op-codes). Затем он выполняет этот сгенерированный код в виртуальной машине.
  6. Расширения — это наборы функций, классов, потоков, доступных PHP-скриптам, которые можно использовать в конкретных задачах. Например, расширение mysql для подключения к базе данных MySQL при помощи PHP.
  7. Когда движок Zend (ZE) выполняет сгенерированный код, скрипт может затребовать доступ к некоторым расширениям. Тогда ZE передаёт управление модулю/слою расширения, который после выполнения задач передаёт управление обратно ZE.
  8. Наконец, движок Zend возвращает результат обратно ядру PHP, которое передаёт его уровню серверного API, которое в конце концов отображает его в вашем браузере.

На шаг глубже

Но подождите! Это ещё не всё. Выше была приведена лишь высокоуровневая блок-схема. Давайте копнём чуть глубже и посмотрим, что ещё происходит за кулисами:

  1. Когда мы запускаем Apache, тот также запускает интерпретатор PHP.
  2. Запуск PHP осуществляется за 2 шага.
  3. Первый шаг — выполнение начальной установки структур и значений, которые сохраняются всё время жизни SAPI.
  4. Второй шаг — для временных настроек, которые существуют только для запроса одной страницы.

Шаг 1 запуска PHP

Запутались в шагах 1 и 2? Нет причин для беспокойства, далее мы обсудим то же самое в деталях. Давайте сначала посмотрим на шаг 1, который обычно является основным. Помните, что шаг 1 происходит даже перед тем, как сделан какой-нибудь запрос страницы.

  1. Когда мы запускаем Apache, он запускает PHP интерпретатор
  2. PHP вызывает метод MINIT каждого подключённого расширения. Посмотрите на свой файл php.ini, чтобы увидеть модули, подключённые по умолчанию.
  3.  MINIT — это модульная инициализация (Module Initialization). Каждый метод модульной инициализации инициализирует и определяет набор функций, классов, которые будут использованы в будущих запросах страниц.

Типичный MINIT-метод выглядит так:

PHP_MINIT_FUNCTION(extension_name) {

/* Инициализация функций, классов и т.д. */

}

Шаг 2 запуска PHP

  1. Когда сделан запрос страницы, уровень SAPI передаёт управление уровню PHP. PHP затем настраивает среду для выполнения запрошенной PHP страницы. Он создаёт символьную таблицу, в которой будут храниться переменные, использующиеся при выполнении этой страницы.
  2. Затем PHP вызывает RINIT-метод каждого модуля. RINIT-модуль — это модуль инициализации запроса (Request Initialization Module). Классический пример реализации RINIT-модуля — модуль сессий. RINIT-метод модуля сессий, если подключен в php.ini, предзаполнит переменную $_SESSION и сохранит её в символьной таблице.
  3. О модуле RINIT можно думать, как о директиве auto_prepend_file, которая добавляется к началу каждого PHP-скрипта перед его выполнением.

Типичный RINIT-метод выглядит так:

PHP_RINIT_FUNCTION(extension_name) {

/* Инициализация переменных сессии, предзаполнение переменных, переопределение глобальных переменных и т.д. */

}

Шаг 1 завершения работы PHP

Так же, как и запуск PHP, его остановка осуществляется за 2 шага.

  1. После завершения выполнения страницы по достижении конца скрипта или из-за вызова функции exit() или die() PHP начинает процесс очистки. Он вызывает метод RSHUTDOWN каждого расширения. RSHUTDOWN можно представить как директиву auto_append_file каждому PHP-скрипту, который будет выполнен при любых обстоятельствах.
  2. Метод RSHUTDOWN удаляет символьную таблицу (управление памятью) посредством вызова unset() для всех переменных в символьной таблице.

Типичный метод RSHUTDOWN выглядит так:

PHP_RSHUTDOWN_FUNCTION(extension_name) {

/* Управление памятью, unset всех переменных, использованных в последнем вызове PHP и т.д. */

}

Шаг 2 завершения работы PHP

Наконец, когда все запросы сделаны, и SAPI готово к завершению работы, PHP приступает к второму шагу завершения работы.

  1. PHP вызывает метод MSHUTDOWN каждого расширения, что является последним шансом для каждого расширения отменить регистрацию обработчиков и высвободить всю память, выделенную во время MINIT-цикла.

Типичный метод MSHUTDOWN выглядит так:

PHP_MSHUTDOWN_FUNCTION(extension_name) {

/* Free handlers and persistent memory etc */

}

И это приводит нас к концу того, что мы называем жизненным циклом PHP. Важно заметить, что шаг 1 запуска и шаг 2 завершения работы происходят, когда не осуществляется никаких запросов к веб-серверам.

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.