PHP 内核之旅系列
PHP 内核之旅 - 1. 生命周期
一, SAPI 是什么?
1.1 理解 SAPI
(1)SAPI 是 PHP 框架的接口层. 有很多种服务器的 SAPI 的实现, 代码在 sapi 文件夹下. 常见的接口抽象层实现有: cgi,apache2,cli,embed,fpm.
(2)各个服务器遵循着相同的约定, 每个服务器的 SAPI 实现都有一套自己的实现. 由于很多操作都是相同的, 所以有一部分使用的是默认方法.
(3)SAPI 类似面向对象中的模板方法模式的应用. SAPI.c 和 SAPI.h 文件所包含的一些函数就是模板方法模式中的抽象模板, 各个服务器对于 sapi_module 的定义及相关实现 (cli,fpm,apache2) 则是一个个具体的模板.
sapi 在源代码中的路径如下:
1.2 调用 SAPI 实现的接口的示意图
上层调用可以是命令行窗口执行 php 脚本, 然后到 SAPI 接口层, 然后具体执行 php 脚本的是 cli(Command Line Interface)接口的方法.
我们就以最简单的 SAPI 接口 Cli 来讲 SAPI 的实现.
二, Cli 是什么?
Cli 即命令行接口, 当在命令行窗口下执行 php 脚本时, 则会调用 Cli.
2.1 直接执行脚本文件
在命令行窗口执行 test.php 脚本
$ php test.php
还可以传递一些指定的参数, 比如
2.2 -r: 直接执行 php 代码
设置变量 $a = 123, 然后打印变量 $a 的值, 并回车换行
$ php -r '$a=123; echo $a ."\r\n";'
打印结果: 123
2.3 -v: 打印 php 的版本号
user@wt01084-048:~$ php -v
PHP 7.2.2-3+ubuntu14.04.1+deb.sury.org+1 (cli) (built: Feb 6 2018 16:35:00) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.2-3+ubuntu14.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
三, Cli 的执行流程?
Cli 是单进程模式. 处理完请求就关闭了.
生命周期:
核心代码:
main 函数位于文件:\sapi\cli\php_cli.c
伪代码如下:
- main()
- {
- // 1. 初始化变量
- ...
- // 2. 定义 sapi_module, 它是记录 SAPI 信息的主要结构.
- // 结构体类型为_sapi_module_struct, 在 \ main\SAPI.h 定义了结构体_sapi_module_struct 类型.
- sapi_module_struct *sapi_module = &cli_sapi_module;
- // 3. 初始化 sapi_module
- sapi_startup(sapi_module); //sapi_startup 函数位于 \ main\SAPI.c
- // 4. 模块初始化阶段
- sapi_module->startup(sapi_module); // 这里的 startup 在结构体_sapi_module_struct 类型中有定义,
- // 而 Cli 定义的 cli_sapi_module 的结构体中 php_cli_startup 指向了 startup, 所以其实就是调用了 php_cli_startup
- // 而 php_cli_startup 直接调用了 php_module_startup()
- // 5. 请求初始化及执行请求
- do_cli();
- // 5.1 根据命令行指定的参数执行相应的操作, 如果是查询系统信息之类的请求(-i,-m,-v), 则会跳过请求初始化阶段
- switch ($args) {
- ...
- }
- // 5.2 请求初始化
- php_request_startup()
- // 5.3 执行脚本
- switch (behavior) {
- case PHP_MODE_STANDARD: // 标准执行模式, 执行脚本文件
- php_execute_script(&file_handle);
- break;
- case ...// 其他执行模式
- }
- // 5.4. 请求关闭阶段
- out:
- php_request_shutdown((void *) 0);
- // 6. 模块关闭阶段
- php_module_shutdown();
- sapi_shutdown();
- }
参考资料: http://www.php-internals.com/
来源: https://www.cnblogs.com/jackson0714/p/php2.html