Где находится основная точка входа 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
,
И так далее.