php_module_startup执行完成后,接下来就执行do_cli, php的主要执行逻辑都在这里。
zend_first_try {
exit_status = do_cli(argc, argv);
} zend_end_try();
do_cli已经来就是检查参数的2个大循环,这里不讨论这些参数,我们以最简单的启动方式来讲:php xxx.php
一、打开脚本文件
if (script_file)
{
if (cli_seek_file_begin(&file_handle, script_file, &lineno) != SUCCESS)
{
goto err;
}
else
{
char real_path[MAXPATHLEN];
if (VCWD_REALPATH(script_file, real_path))
{
translated_path = strdup(real_path);
}
script_filename = script_file;
}
}
二、php_request_startup 启动请求
这个函数内容比较多,接下来就讲这个
三、zend_interned_strings_activate 初始化本次请求的字符串表
ZEND_API void zend_interned_strings_activate(void)
{
zend_init_interned_strings_ht(&CG(interned_strings), 0);
}
四、php_output_activate 初始化输出结构
PHPAPI int php_output_activate(void)
{
memset(&output_globals, 0, sizeof(zend_output_globals));
zend_stack_init(&OG(handlers), sizeof(php_output_handler *));
OG(flags) |= PHP_OUTPUT_ACTIVATED;
return SUCCESS;
}
五、zend_activate 激活zend引擎
包括一下操作:
1. gc_reset: 重置gc
2. init_compiler: 初始化编译器
3. init_executor: 初始化执行器
4. startup_scanner: 初始化词法分析和语法分析
以上四个每一个展开都很大,这里暂时不写。
六、sapi_activate 初始化sapi
这里包括四个过程:
1. 初始化 sapi_globals 结构
2. 如果是"post"方式请求,这读取post数据
3. 读取cookies
4. 调用sapi_module的activate函数和input_filter_init函数(假如不为空)
七、zend_signal_activate 注册系统信号的回调
# define SIGG(v) (zend_signal_globals.v)
void zend_signal_activate(void)
{
size_t x;
memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
zend_signal_register(zend_sigs[x], zend_signal_handler_defer);
}
SIGG(active) = 1;
SIGG(depth) = 0;
}
八、设置输入的超时时间(从接收所有数据到执行脚本的时间)
if (PG(max_input_time) == -1) {
zend_set_timeout(EG(timeout_seconds), 1);
} else {
zend_set_timeout(PG(max_input_time), 1);
}
九、response里增加php版本号的头
#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
if (PG(expose_php)) {
sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
}
是否增加这个头,取决于ini的配置,默认是有这个头。
十、输出控制
if (PG(output_handler) && PG(output_handler)[0]) {
zval oh;
ZVAL_STRING(&oh, PG(output_handler));
php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
zval_ptr_dtor(&oh);
} else if (PG(output_buffering)) {
php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
} else if (PG(implicit_flush)) {
php_output_set_implicit_flush(1);
}
有三种互斥的输出控制
1. 重定向到一个内部输出函数
2. 输出控制。在cli模式下,这个无效
3. 输出即时刷新。在cli模式下,这个一直有效
累了,明天再写。