php-src/PHP-Internals 主入口点在哪里
Where's the php-src/PHP-Internals Main Entry Point
source of PHP itself 中 PHP 程序的 executing/interpreting 的主要入口点是什么函数或代码?根据我在谷歌上搜索或阅读的内容,我知道 PHP 旨在与某种服务器一起工作(甚至 CLI 命令也可以通过启动 "the command line SAPI" 来工作,它充当一个迷你-server 旨在处理单个请求),并且服务器将要求 PHP 执行程序。
我知道 minit
和 rinit
生命周期函数,它们作为 PHP 扩展的入口点.
我不知道 PHP 源代码在哪里与自己对话
Hey look, there's a PHP program in this file/string. I ought to run it
我不想在这里完成任何特定任务。我试图了解 PHP 的内部结构是如何工作的,并找到一个主要入口点,我可以在其中开始执行它。
某些SAPI的代码入口在哪里?
CLI 是一个独立的应用程序。与用 C 编写的任何其他应用程序一样,它的入口点是函数 main()
(文件 sapi/cli/php_cli.c
, line 1200
):
int main(int argc, char *argv[])
Windows 有两个版本的 CLI,其中一个是控制台应用程序,以上述 main()
功能启动,另一个是 Windows GUI 应用程序(它在启动时不创建控制台并使用消息框进行输出)以 WinMain()
函数(文件 sapi/cli/php_cli.c
, line 1198
)开始。
main()
和 WinMain()
在这里使用相同的代码。通过检查是否定义了符号 PHP_CLI_WIN32_NO_CONSOLE
,它们在各处具有不同的名称和不同的代码片段。它在用于生成 Windows GUI 应用程序的文件 sapi/cli/cli_win32.c
中定义。
</Windows>
CGI版本也是一个独立的控制台应用程序。它的入口点也是文件sapi/cgi/cgi_main.c
, line 1792
.
中的main()
函数
类似的,FPM版本在文件sapi/fpm/fpm/fpm_main.c
, line 1570
.
中以main()
开头
Apache2 处理程序 是一个可动态加载的模块(.dll
在 Windows 上,.so
在 Unix-like 系统上)。它将一些函数注册为 Web 服务器发布的事件的事件处理程序(服务器启动、pre/post 配置加载、处理请求等)。这些处理程序由文件 sapi/apache2handler/sapi_apache2.c
, line 738
.
中的 php_ap2_register_hook()
函数注册
(您可以在 Apache documentation 中找到有关可加载模块如何与 Apache 集成的详细信息。)
我们感兴趣的处理程序是调用函数 php_handler()
来处理 HTTP 请求。
以类似的方式,每个 SAPI 都有一个入口点(main()
或由 Web 服务器调用的函数)。
所有这些入口点都做类似的处理:
- 初始化自己;
- 解析命令行参数(仅当它是 CLI、CGI 或其他类型的独立应用程序时);
- 阅读
php.ini
and/or他们有的其他配置(Apache模块配置可以在.htaccess
中被覆盖);
- 使用输入文件创建流并将其传递给函数
php_execute_script()
defined in file main/main.c
, line 2496
;
- 清理和 return 调用进程(shell 或网络服务器)的退出代码。
实际执行 PHP 脚本的代码在哪里?
处理它们的函数 php_execute_script()
is a wrapper; it interprets the php.ini
configuration entries auto_prepend_file
and auto_append_file
, prepares the list of files (auto-prepend file, main script, auto-append file) and passes the list to zend_execute_scripts()
。
php_execute_script()
并不总是被调用,某些 SAPI 和 CLI 的命令行参数会产生 zend_execute_scripts()
.
的直接调用
zend_execute_scripts()
是有趣的事情发生的地方。
它compiles the PHP file (and returns a list of OP codes in op_array
then, if the compilation succeeds (the returned op_array
is not NULL
) it executes OP-codes。还有异常处理和清理;无聊的工作,但与解析和执行一样重要。
编译是一个繁琐的过程。这是由文件 Zend/zend_language_parser.c
中定义的函数 zendparse()
完成的。 zendparse()
函数的定义和文件 Zend/zend_language_parser.c
在 Git 仓库中无处可见;解析器是使用 bison
和 re2c
生成的,它们从 Zend/zend_language_parser.y
and Zend/zend_language_scanner.l
读取语言语法规则和词法标记的定义,并在文件 Zend/zend_language_parser.c
.[=99 中生成实际的编译器=]
然而,即使回购中看不到辛苦的工作,编译过程中有趣的部分在上面提到的文件中是可见的。
编译脚本(OP 代码列表)的执行由文件 Zend/zend_vm_execute.h
中定义的函数 zend_execute()
完成。这也是一个生成的文件,有趣的是它是由 PHP 脚本生成的。
生成器脚本 (Zend/zend_vm_gen.php
) uses zend_vm_def.h
and zend_vm_execute.skl
to generate zend_vm_execute.h
and zend_vm_opcodes.h
.
zend_vm_def.h
包含执行以处理每个 OP 代码的实际解释器代码。
PHP 核心或其捆绑扩展之一提供的某些功能的代码在哪里?
PHP 函数和扩展提供的函数的代码在某种程度上更容易理解。 PHP 核心中包含的函数位于 ext/standard
directory, the functions provided by other extensions are located in files in the corresponding ext
子目录中的文件中。
在这些文件中,实现 PHP 函数的 C 函数是使用 PHP_FUNCTION()
宏声明的。比如PHP函数的实现strpos()
从文件 ext/standard/string.c
, line 1948
. The function strchr()
being an alias of strstr()
is declared using the PHP_FALIAS()
macro in file ext/standard/basic_functions.c
on line 2833
.
开始
等等,等等。
source of PHP itself 中 PHP 程序的 executing/interpreting 的主要入口点是什么函数或代码?根据我在谷歌上搜索或阅读的内容,我知道 PHP 旨在与某种服务器一起工作(甚至 CLI 命令也可以通过启动 "the command line SAPI" 来工作,它充当一个迷你-server 旨在处理单个请求),并且服务器将要求 PHP 执行程序。
我知道 minit
和 rinit
生命周期函数,它们作为 PHP 扩展的入口点.
我不知道 PHP 源代码在哪里与自己对话
Hey look, there's a PHP program in this file/string. I ought to run it
我不想在这里完成任何特定任务。我试图了解 PHP 的内部结构是如何工作的,并找到一个主要入口点,我可以在其中开始执行它。
某些SAPI的代码入口在哪里?
CLI 是一个独立的应用程序。与用 C 编写的任何其他应用程序一样,它的入口点是函数 main()
(文件 sapi/cli/php_cli.c
, line 1200
):
int main(int argc, char *argv[])
Windows 有两个版本的 CLI,其中一个是控制台应用程序,以上述 main()
功能启动,另一个是 Windows GUI 应用程序(它在启动时不创建控制台并使用消息框进行输出)以 WinMain()
函数(文件 sapi/cli/php_cli.c
, line 1198
)开始。
main()
和 WinMain()
在这里使用相同的代码。通过检查是否定义了符号 PHP_CLI_WIN32_NO_CONSOLE
,它们在各处具有不同的名称和不同的代码片段。它在用于生成 Windows GUI 应用程序的文件 sapi/cli/cli_win32.c
中定义。
</Windows>
CGI版本也是一个独立的控制台应用程序。它的入口点也是文件sapi/cgi/cgi_main.c
, line 1792
.
main()
函数
类似的,FPM版本在文件sapi/fpm/fpm/fpm_main.c
, line 1570
.
main()
开头
Apache2 处理程序 是一个可动态加载的模块(.dll
在 Windows 上,.so
在 Unix-like 系统上)。它将一些函数注册为 Web 服务器发布的事件的事件处理程序(服务器启动、pre/post 配置加载、处理请求等)。这些处理程序由文件 sapi/apache2handler/sapi_apache2.c
, line 738
.
中的 php_ap2_register_hook()
函数注册
(您可以在 Apache documentation 中找到有关可加载模块如何与 Apache 集成的详细信息。)
我们感兴趣的处理程序是调用函数 php_handler()
来处理 HTTP 请求。
以类似的方式,每个 SAPI 都有一个入口点(main()
或由 Web 服务器调用的函数)。
所有这些入口点都做类似的处理:
- 初始化自己;
- 解析命令行参数(仅当它是 CLI、CGI 或其他类型的独立应用程序时);
- 阅读
php.ini
and/or他们有的其他配置(Apache模块配置可以在.htaccess
中被覆盖); - 使用输入文件创建流并将其传递给函数
php_execute_script()
defined in filemain/main.c
, line2496
; - 清理和 return 调用进程(shell 或网络服务器)的退出代码。
实际执行 PHP 脚本的代码在哪里?
处理它们的函数 php_execute_script()
is a wrapper; it interprets the php.ini
configuration entries auto_prepend_file
and auto_append_file
, prepares the list of files (auto-prepend file, main script, auto-append file) and passes the list to zend_execute_scripts()
。
php_execute_script()
并不总是被调用,某些 SAPI 和 CLI 的命令行参数会产生 zend_execute_scripts()
.
zend_execute_scripts()
是有趣的事情发生的地方。
它compiles the PHP file (and returns a list of OP codes in op_array
then, if the compilation succeeds (the returned op_array
is not NULL
) it executes OP-codes。还有异常处理和清理;无聊的工作,但与解析和执行一样重要。
编译是一个繁琐的过程。这是由文件 Zend/zend_language_parser.c
中定义的函数 zendparse()
完成的。 zendparse()
函数的定义和文件 Zend/zend_language_parser.c
在 Git 仓库中无处可见;解析器是使用 bison
和 re2c
生成的,它们从 Zend/zend_language_parser.y
and Zend/zend_language_scanner.l
读取语言语法规则和词法标记的定义,并在文件 Zend/zend_language_parser.c
.[=99 中生成实际的编译器=]
然而,即使回购中看不到辛苦的工作,编译过程中有趣的部分在上面提到的文件中是可见的。
编译脚本(OP 代码列表)的执行由文件 Zend/zend_vm_execute.h
中定义的函数 zend_execute()
完成。这也是一个生成的文件,有趣的是它是由 PHP 脚本生成的。
生成器脚本 (Zend/zend_vm_gen.php
) uses zend_vm_def.h
and zend_vm_execute.skl
to generate zend_vm_execute.h
and zend_vm_opcodes.h
.
zend_vm_def.h
包含执行以处理每个 OP 代码的实际解释器代码。
PHP 核心或其捆绑扩展之一提供的某些功能的代码在哪里?
PHP 函数和扩展提供的函数的代码在某种程度上更容易理解。 PHP 核心中包含的函数位于 ext/standard
directory, the functions provided by other extensions are located in files in the corresponding ext
子目录中的文件中。
在这些文件中,实现 PHP 函数的 C 函数是使用 PHP_FUNCTION()
宏声明的。比如PHP函数的实现strpos()
从文件 ext/standard/string.c
, line 1948
. The function strchr()
being an alias of strstr()
is declared using the PHP_FALIAS()
macro in file ext/standard/basic_functions.c
on line 2833
.
等等,等等。