Где находится основная точка входа php-src/PHP-Internals

Какая функция или фрагмент кода служит основной точкой входа для выполнения / интерпретации PHP-программы в самом источнике PHP? Основываясь на вещах, которые я гуглил или читал в книгах, я знаю, что PHP предназначен для работы с каким-либо сервером (даже команда CLI работает, запуская "командную строку SAPI", которая действует как мини-сервер, разработанный обработать один запрос), и что сервер попросит PHP выполнить программу.

Я знаю о minit а также rinit функции жизненного цикла, которые служат точками входа для расширения PHP.

Чего я не знаю, так это где исходный код PHP ведет этот разговор с самим собой

Слушай, в этом файле / строке есть PHP-программа. Я должен запустить это

Я не пытаюсь выполнить какую-то конкретную задачу здесь. Я пытаюсь понять, как внутренняя часть PHP делает то, что он делает, и найти основную точку входа, где я могу начать следить за его выполнением.

1 ответ

Решение

Где находится точка входа в код какого-то SAPI?

CLI - это отдельное приложение. Как и любое другое приложение, написанное на C, его точкой входа является функция main() (файл sapi/cli/php_cli.c, линия 1200):

int main(int argc, char *argv[])

Существует две версии интерфейса командной строки для Windows, одна из которых является консольным приложением и начинается с main() описанная выше функция, другая - приложение с графическим интерфейсом Windows (оно не создает консоль при запуске и использует окна сообщений для вывода), которое начинается с WinMain() функция (файл sapi/cli/php_cli.c, линия 1198).
main() а также WinMain() используйте тот же код здесь. Они имеют разные названия и разные фрагменты кода здесь и там, проверяя, если символ PHP_CLI_WIN32_NO_CONSOLE определено. Определяется в файле sapi/cli/cli_win32.c это используется для создания приложения Windows GUI.
</Windows>

Версия CGI также является автономным консольным приложением. Его точкой входа также является main() функция в файле sapi/cgi/cgi_main.c, линия 1792,

Похоже, версия FPM начинается с main() в файле sapi/fpm/fpm/fpm_main.c, линия 1570,

Обработчик Apache2 - это динамически загружаемый модуль (.dll в Windows, .so в Unix-подобных системах). Он регистрирует некоторые функции в качестве обработчиков событий для событий, публикуемых веб-сервером (запуск сервера, загрузка до / после конфигурации, запрос процесса и т. Д.). Эти обработчики зарегистрированы php_ap2_register_hook() функция в файле sapi/apache2handler/sapi_apache2.c, линия 738,
(Подробную информацию о том, как загружаемый модуль интегрируется с Apache, можно найти в документации по Apache.)

Интересующий нас обработчик - это функция php_handler() это вызывается для обработки HTTP-запроса.

Аналогичным образом, каждый SAPI имеет точку входа (либо main() или функция, которая вызывается веб-сервером).

Все эти точки входа выполняют аналогичную обработку:

  • инициализировать себя;
  • разбирать аргументы командной строки (только если это CLI, CGI или другой вид автономного приложения);
  • читать php.ini и / или другая конфигурация, которую они имеют (конфигурация модуля Apache может быть переопределена в .htaccess);
  • создайте поток, используя входной файл, и передайте его функции php_execute_script() определено в файле main/main.c, линия 2496;
  • очистить и вернуть код завершения вызывающему процессу (оболочке или веб-серверу).

Где код, который на самом деле выполняет скрипт PHP?

Функция php_execute_script() это обертка; это интерпретирует php.ini записи конфигурации auto_prepend_fileа также auto_append_file, подготавливает список файлов (файл с автоматическим добавлением, основной скрипт, файл с автоматическим добавлением) и передает список zend_execute_scripts() это обрабатывает их.

php_execute_script() не всегда вызывается, некоторые SAPI и аргументы командной строки CLI производят прямой вызов zend_execute_scripts(),

zend_execute_scripts() Здесь происходят интересные вещи.

Он компилирует файл PHP (и возвращает список кодов OP в op_array затем, если компиляция завершится успешно op_array не является NULL) выполняет ОП-коды. Также есть обработка и очистка исключений; скучная работа, но так же важная, как разбор и выполнение.

Компиляция - утомительный процесс. Это делается функцией zendparse() определено в файле Zend/zend_language_parser.c, Определение zendparse() функция и файл Zend/zend_language_parser.c нигде не видно в репозитории Git; парсер генерируется с помощью bison а также re2c которые читают правила синтаксиса языка и определение лексических токенов из Zend/zend_language_parser.y а также Zend/zend_language_scanner.l и сгенерировать фактический компилятор в файле Zend/zend_language_parser.c,

Однако, даже если тяжелая работа не видна в репо, интересные части процесса компиляции видны в файлах, упомянутых выше.

Выполнение скомпилированного скрипта (список кодов OP) выполняется функцией zend_execute() это определено в файле Zend/zend_vm_execute.h, Это также сгенерированный файл, и интересная часть заключается в том, что он генерируется скриптом PHP.

Скрипт генератора (Zend/zend_vm_gen.php) использует zend_vm_def.h а также zend_vm_execute.skl чтобы генерировать zend_vm_execute.h а также zend_vm_opcodes.h,

zend_vm_def.h содержит фактический код интерпретатора, который выполняется для обработки каждого кода OP.

Где находится код какой-либо функции, предоставляемой ядром PHP или одним из его расширений?

Код функций и функций PHP, предоставляемых расширениями, как-то проще следовать. Функции, включенные в ядро ​​PHP, расположены в файлах в ext/standard каталог, функции, предоставляемые другими расширениями, находятся в файлах в соответствующем ext подкаталоги.

В этих файлах функции C, которые реализуют функции PHP, объявляются с использованием PHP_FUNCTION() макро. Например, реализация функции PHP strpos() начинается в файле ext/standard/string.c, линия 1948, Функция strchr() быть псевдонимом strstr() объявлен с использованием PHP_FALIAS() макрос в файле ext/standard/basic_functions.c онлайн 2833,

И так далее.

Другие вопросы по тегам