模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=test.so,存放到数据结构zend_extensions中 模块的数据结构: struct _zend_extension { // zend扩展模块结构体(php.ini中以zend_extension开头的配置,如zend_extension=test.so) char *name; // zend 扩展名 char *version; // 版本 char *author; // 作者 char *URL; // char *copyright; startup_func_t startup; // 启动函数(启动时执行一次) !!! shutdown_func_t shutdown; // 停止函数 !!! activate_func_t activate; // 激活函数 !!! deactivate_func_t deactivate; // 失活函数 !!! message_handler_func_t message_handler; // 接受消息通知,如:添加新模块的消息通知 !!! op_array_handler_func_t op_array_handler; // opcode处理 !!!! statement_handler_func_t statement_handler; // !!!! fcall_begin_handler_func_t fcall_begin_handler; // !!!! fcall_end_handler_func_t fcall_end_handler; // !!!! op_array_ctor_func_t op_array_ctor; // opcode构造!!! op_array_dtor_func_t op_array_dtor; // opcode析构!!! int (*api_no_check)(int api_no); int (*build_id_check)(const char* build_id); void *reserved3; void *reserved4; void *reserved5; void *reserved6; void *reserved7; void *reserved8; DL_HANDLE handle; // *.so模块的的内存句柄(类似zend_extension=test.so) int resource_number; }; 类型二:php的模块:(类似extension=test.so) 识别方法: php.ini中以extension开头的配置,如extension=test.so,存放到数据结构module_registry中 模块的数据结构: struct _zend_module_entry { // php扩展模块结构体(php.ini中以extension开头的配置,如extension=test.so) unsigned short size; unsigned int zend_api; unsigned char zend_debug; unsigned char zts; const struct _zend_ini_entry *ini_entry; const struct _zend_module_dep *deps; // 模块依赖 const char *name; // 模块名,如 "Core" const struct _zend_function_entry *functions; // 模块函数 int (*module_startup_func)(INIT_FUNC_ARGS); // 启动函数(启动时执行一次)!!! int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); // 停止函数 !!! int (*request_startup_func)(INIT_FUNC_ARGS); // 请求函数(启动一次,可以接受多次请求)!!! int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); // 请求关闭函数!!! void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); // 信息函数,执行phpinfo时,会调用本方法获取概要信息 const char *version; // 版本 size_t globals_size; #ifdef ZTS ts_rsrc_id* globals_id_ptr; #else void* globals_ptr; #endif void (*globals_ctor)(void *global TSRMLS_DC); // 构造函数 void (*globals_dtor)(void *global TSRMLS_DC); // 析构函数 int (*post_deactivate_func)(void); // 请求失活函数!!! int module_started; unsigned char type; void *handle; // *.so模块的的内存句柄(类似extension=test.so) int module_number; const char *build_id; }; 模块调用埋点 // 在文件 php-5.6.26\sapi\cgi\cgi_main.c int main(int argc, char *argv[]) { .... cgi_sapi_module->startup(){ // php_cgi_startup实现在文件 php-5.6.26\sapi\cgi\cgi_main.c static int php_cgi_startup(sapi_module_struct *sapi_module) { // php_module_startup实现在文件 php-5.6.26\main\main.c if (php_module_startup(sapi_module, &cgi_module_entry, 1){ .... // 启动zend引擎(创建“全局函数表”、“全局类表”、“全局常量表”、“模块注册表”......) zend_startup(&zuf, NULL TSRMLS_CC); // !!!! ... // 注册常量 REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); // 注册到 EG(zend_constants) REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS); ... php_binary_init(TSRMLS_C); // 执行文件的地址放入 PG(php_binary) = sapi_module.executable_location ... php_output_register_constants(TSRMLS_C); // 注册常量 PHP_OUTPUT_HANDLER_START 等... php_rfc1867_register_constants(TSRMLS_C); // 注册常量 UPLOAD_ERR_OK 等... /* this will read in php.ini, set up the configuration parameters, load zend extensions and register php function extensions to be loaded later */ if (php_init_config(TSRMLS_C) == FAILURE) { // !!!! 解析 php.ini 文件,加载zend扩展 return FAILURE; } /* Register PHP core ini entries */ REGISTER_INI_ENTRIES(); // 设置php核心的ini配置 zend_register_ini_entries(ini_entries, module_number TSRMLS_CC) /* Register Zend ini entries */ zend_register_standard_ini_entries(TSRMLS_C); // 设置zend的ini的配置 .... php_startup_auto_globals(TSRMLS_C); // 注册"_GET"、"_POST"、"_COOKIE"、"_SERVER"的处理函数到CG(auto_globals) zend_set_utility_values(&zuv); php_startup_sapi_content_types(TSRMLS_C); // 设置sapi_module.default_post_reader sapi_module.xxx 的值 /* startup extensions statically compiled in */ // php_register_internal_extensions php_register_extensions if (php_register_internal_extensions_func(TSRMLS_C) == FAILURE) { // 迭代“内建模块列表”,添加内建模块信息到“模块注册表module_registry”、注册“模块的函数”到 CG(function_table) php_printf("Unable to start builtin modules\n"); return FAILURE; } /* start additional PHP extensions */ php_register_extensions_bc(additional_modules, num_additional_modules TSRMLS_CC); // 添加additional_modules模块信息到“模块注册表module_registry”、注册“模块的函数”到 CG(function_table) /* load and startup extensions compiled as shared objects (aka DLLs) as requested by php.ini entries theese are loaded after initialization of internal extensions as extensions *might* rely on things from ext/standard which is always an internal extension and to be initialized ahead of all other internals */ // php_ini_register_extensions实现在文件 php-5.6.26\main\php_ini.c php_ini_register_extensions(TSRMLS_C); // 1、加载引擎的扩展模块,并把扩展信息添加到链表 zend_extensions 中(php.ini中以zend_extension开头的配置,如zend_extension=test.so) 2、加载extension_dir用户扩展模块,并把模块信息添加到模块注册表module_registry中 (php.ini中以extension开头的配置,如extension=test.so) { zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC); // 加载引擎的扩展模块,并把扩展信息添加到链表 zend_extensions 中(php.ini中以zend_extension开头的配置,如zend_extension=test.so) { // php_load_zend_extension_cb实现在文件 php-5.6.26\main\php_ini.c static void php_load_zend_extension_cb(void *arg TSRMLS_DC) { char *filename = *((char **) arg); // 扩展名 int length = strlen(filename); if (IS_ABSOLUTE_PATH(filename, length)) { zend_load_extension(filename); // 把扩展添加到链表zend_extensions中 { ... handle = DL_LOAD(path); // --------加载动态链接库 ... extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info"); // 获取扩展版本信息 if (!extension_version_info) { extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info"); } new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry"); // 扩指定入口 if (!new_extension) { new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry"); } ... // zend_register_extension实现在文件 php-5.6.26\Zend\zend_extensions.c return zend_register_extension(new_extension, handle); // !!!注册扩展信息,并迭代执行“类似zend_extension=test.so模块”的 message_handler 方法 { #if ZEND_EXTENSIONS_SUPPORT zend_extension extension; extension = *new_extension; extension.handle = handle; // 动态链接库引用 // zend_extension_dispatch_message实现在文件 php-5.6.26\Zend\zend_extensions.c // #define ZEND_EXTMSG_NEW_EXTENSION 1 zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension); // 迭代执行“类似zend_extension=test.so模块”的 message_handler 方法 { TSRMLS_FETCH(); // zend_extension_dispatch_message实现在文件 php-5.6.26\Zend\zend_extensions.c // 迭代执行“类似zend_extension=test.so模块”的 message_handler 方法 zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher TSRMLS_CC, 2, message, arg); { int message; void *arg; if (!extension->message_handler || num_args!=2) { return; } message = va_arg(args, int); arg = va_arg(args, void *); extension->message_handler(message, arg); // -------------------------------- 执行“类似zend_extension=test.so模块”的 message_handler 方法 } } zend_llist_add_element(&zend_extensions, &extension); // 把扩展添加到链表zend_extensions中 /*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/ #endif return SUCCESS; } } } else { char *libpath; char *extension_dir = INI_STR("extension_dir"); // 扩展目录 int extension_dir_len = strlen(extension_dir); if (IS_SLASH(extension_dir[extension_dir_len-1])) { spprintf(&libpath, 0, "%s%s", extension_dir, filename); } else { spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); } zend_load_extension(libpath); efree(libpath); } } } zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC); // 加载extension_dir用户扩展模块,并把模块信息添加到模块注册表module_registry中 (php.ini中以extension开头的配置,如extension=test.so) zend_llist_destroy(&extension_lists.engine); zend_llist_destroy(&extension_lists.functions); } zend_startup_modules(TSRMLS_C); // !!!迭代 module_registry 中的模块,依次调用每个模块的 module_startup_func 方法 -------------------------------------- 迭代调用“【类似extension=test.so模块】的启动方法module_startup_func” /* start Zend extensions */ zend_startup_extensions(); // !!!迭代 zend_extensions 中的模块,依次调用每个模块的 startup 方法 -------------------------------------- 迭代调用“【类似zend_extension=test.so模块】的启动方法startup” // !!!! 收集、归类模块的“处理函数” -------------------------------------- 收集归类【类似extension=test.so模块】的“处理函数”(1.请求接受module_request_startup_handlers、2.请求结束module_request_shutdown_handlers、3.post失效module_post_deactivate_handlers) zend_collect_module_handlers(TSRMLS_C); // 1、模块的请求到达时,调用的函数,并放入module_request_startup_handlers 2、模块的请求关闭时,调用的函数,并放入 module_request_shutdown_handlers 3、模块失活时,调用的函数,并放入 module_post_deactivate_handlers /* register additional functions */ if (sapi_module.additional_functions) { if (zend_hash_find(&module_registry, "standard", sizeof("standard"), (void**)&module)==SUCCESS) { // 存在名为standard的php扩展模块 EG(current_module) = module; zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); // 注册sapi_module.additional_functions函数列表到HashTable 类型的CG(function_table)中 EG(current_module) = NULL; } } /* disable certain classes and functions as requested by php.ini */ php_disable_functions(TSRMLS_C); // 禁止掉php.ini配置中定义禁止的函数(篡改函数的handler指向),disable_functions="eval,substr" php_disable_classes(TSRMLS_C); // 禁止掉php.ini配置中定义禁止的类(篡改构造函数的handler指向),disable_classes="Pdo,Soap" /* make core report what it should */ if (zend_hash_find(&module_registry, "core", sizeof("core"), (void**)&module)==SUCCESS) { // 存在名为 core 的php扩展模块 module->version = PHP_VERSION; // 核心扩展的版本 module->info_func = PHP_MINFO(php_core); // 核心扩展的信息 } .... } == FAILURE) { return FAILURE; } return SUCCESS; } } .... while (!fastcgi || fcgi_accept_request(request) >= 0) { // 接受到socket请求 req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); /* request startup only after we've done all we can to * get path_translated */ // php_request_startup实现在文件 php-5.6.26\main\main.c if (php_request_startup(TSRMLS_C){ ... zend_activate(TSRMLS_C); // 重置内存回收器、初始化zend编译器、初始化zend执行器、启动zend扫描器、--------------------------------------迭代执行“类似zend_extension=test.so模块”的 activate 方法 等。。。 sapi_activate(TSRMLS_C); // 读取post数据、读取cookie .... php_hash_environment(TSRMLS_C); zend_activate_modules(TSRMLS_C); // --------------------------------------迭代执行“类似extension=test.so扩展”的 request_startup_func 函数 } == FAILURE) { // 启动处理请求。 激活输出空间,初始化 OG(handlers)结构体、设置php全局核心、重置内存回收器、初始化zend编译器、初始化zend执行器、启动zend扫描器、读取cookie、设执行超时时间EG(timeout_seconds)、调用所有模块的请求的函数 zend_module_entry->request_startup_func() if (fastcgi) { fcgi_finish_request(request, 1); // 回收request对象 } SG(server_context) = NULL; // --------------------------------------回收module_registry对象,迭代执行“类似extension=test.so扩展”的 module_shutdown_func 函数 // --------------------------------------迭代执行“类似zend_extension=test.so模块”的shutdown方法 php_module_shutdown(TSRMLS_C); return FAILURE; } if (no_headers) { SG(headers_sent) = 1; SG(request_info).no_headers = 1; } ... switch (behavior) { case PHP_MODE_STANDARD: // php_execute_script实现在文件 php-5.6.26\main\main.c php_execute_script(&file_handle TSRMLS_CC); // 执行php文件!!! { .... if (CG(start_lineno) && prepend_file_p) { int orig_start_lineno = CG(start_lineno); CG(start_lineno) = 0; if (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, prepend_file_p) == SUCCESS) { CG(start_lineno) = orig_start_lineno; retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 2, primary_file, append_file_p) == SUCCESS); } } else { // php_execute_script实现在文件 php-5.6.26\Zend\zend.c retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS); // 执行primary_file的php脚本 { ... va_start(files, file_count); for (i = 0; i < file_count; i++) { // file_handle = va_arg(files, zend_file_handle *); // 获取文件名(前置文件、主文件、后置文件) if (!file_handle) { continue; } if (orig_interactive) { if (file_handle->filename[0] != '-' || file_handle->filename[1]) { CG(interactive) = 0; } else { CG(interactive) = 1; } } // compile_file实现在文件 php-5.6.26\Zend\zend_language_scanner.c EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC); // 编译PHP文件成操作码 op_code ,zend_compile_file == compile_file { if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { // 打开文件、设置扫描器的指针 if (type==ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); zend_bailout(); } else { zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); } compilation_successful=0; } else { // init_op_array实现在文件 php-5.6.26\Zend\zend_opcode.c // 扫描后、初始化 op_array init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); // 1、初始化一些数据、申请空间 2、迭代调用所有 zend_extensions 扩展的 op_array_ctor 函数 { ... // --------------------------------------迭代执行“类似zend_extension=test.so模块”的op_array_ctor方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC); // 迭代调用所有zend扩展的op_array_ctor函数 } CG(in_compilation) = 1; // 是否处于汇编状态 CG(active_op_array) = op_array; // 操作码数组 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); // 把当前上下文入栈 zend_init_compiler_context(TSRMLS_C); // 初始化编译器上下文 compiler_result = zendparse(TSRMLS_C); // 开始解析 zendparse == phpparse == yyparse zend_do_return(&retval_znode, 0 TSRMLS_CC); // 返回 CG(in_compilation) = original_in_compilation; // 还原现场 if (compiler_result != 0) { /* parser error */ zend_bailout(); } compilation_successful=1; // 汇编成功 } if (retval) { CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场) if (compilation_successful) { // 汇编成功 // pass_two实现在文件 php-5.6.26\Zend\zend_opcode.c pass_two(op_array TSRMLS_CC); // !!!! 给每个op_code注册“op_code处理器” { if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) { // ------------------------------------- 迭代执行“类似zend_extension=test.so模块”的 op_array_handler 方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC); { // zend_extension_op_array_handler 实现在文件 php-5.6.26\Zend\zend_opcode.c static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) { if (extension->op_array_handler) { extension->op_array_handler(op_array); } } } } .... while (opline < end) { // 迭代所有操作码 ... ZEND_VM_SET_OPCODE_HANDLER(opline); // 注入“opcode处理器” !!!! 如:ZEND_EXT_STMT_SPEC_HANDLER opline++; } ... } zend_release_labels(0 TSRMLS_CC); } else { efree(op_array); retval = NULL; } } zend_restore_lexical_state(&original_lex_state TSRMLS_CC); // 还原原来词法解析器的状态(还原现场) return retval; } if (file_handle->opened_path) { int dummy = 1; zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path) + 1, (void *)&dummy, sizeof(int), NULL); // included 的文件列表 } zend_destroy_file_handle(file_handle TSRMLS_CC); // 销毁文件句柄 if (EG(active_op_array)) { // “操作码”数组 EG(return_value_ptr_ptr) = retval ? retval : NULL; zend_execute(EG(active_op_array) TSRMLS_CC); // 执行编译后的操作码 op_code , zend_execute { if (EG(exception)) { return; } zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); // zend_execute_ex = execute_ex { // execute_ex实现在文件 php-5.6.26\Zend\zend_vm_execute.h ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { ... if (0) { zend_vm_enter: execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); } ... while (1) { int ret; #ifdef ZEND_WIN32 if (EG(timed_out)) { zend_timeout(0); } #endif /* OPLINE->handler(execute_data TSRMLS_CC) EX(opline)->handler(execute_data TSRMLS_CC) execute_data.opline->handler(execute_data TSRMLS_CC) */ if ((ret = OPLINE->handler(execute_data TSRMLS_CC)){ 如:OPLINE->handler == ZEND_EXT_STMT_SPEC_HANDLER { static int ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); if (!EG(no_extensions)) { // -------------------------------------- 迭代执行“类似zend_extension=test.so模块”的 statement_handler 方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } } 如:OPLINE->handler == ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER{ static int ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); if (!EG(no_extensions)) { // -------------------------------------- 迭代执行“类似zend_extension=test.so模块”的 fcall_begin_handler 方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } } 如:OPLINE->handler == ZEND_EXT_FCALL_END_SPEC_HANDLER{ static int ZEND_FASTCALL ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); if (!EG(no_extensions)) { // -------------------------------------- 迭代执行“类似zend_extension=test.so模块”的 fcall_end_handler 方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } } } > 0) { // execute_data.opline->handler(execute_data TSRMLS_CC) // 调用“opcode对应的处理函数” switch (ret) { case 1: EG(in_execution) = original_in_execution; // 还原现场 return; case 2: goto zend_vm_enter; // 进入虚拟机 break; case 3: execute_data = EG(current_execute_data); // 当前正在执行的数据 break; default: break; } } } } } } zend_exception_restore(TSRMLS_C); // 还原异常 if (EG(exception)) { // 检查异常 if (EG(user_exception_handler)) { // 用户的异常处理器 zval *orig_user_exception_handler; zval **params[1], *retval2, *old_exception; old_exception = EG(exception); EG(exception) = NULL; params[0] = &old_exception; orig_user_exception_handler = EG(user_exception_handler); if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) { // 调用用户的异常处理器 if (retval2 != NULL) { zval_ptr_dtor(&retval2); } if (EG(exception)) { zval_ptr_dtor(&EG(exception)); EG(exception) = NULL; } zval_ptr_dtor(&old_exception); } else { EG(exception) = old_exception; zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } } else { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } } // destroy_op_array实现在文件 php-5.6.26\Zend\zend_opcode.c destroy_op_array(EG(active_op_array) TSRMLS_CC); // 迭代执行所有 zend_extensions 扩展的 op_array_dtor 函数 { if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) { // --------------------------------------迭代执行“类似zend_extension=test.so模块”的op_array_dtor方法 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC); // 迭代执行所有 zend_extensions 扩展的 op_array_dtor 函数 } } efree(EG(active_op_array)); } else if (type==ZEND_REQUIRE) { va_end(files); EG(active_op_array) = orig_op_array; EG(return_value_ptr_ptr) = orig_retval_ptr_ptr; CG(interactive) = orig_interactive; return FAILURE; } } va_end(files); ... } } .... } break; ... } ... fastcgi_request_done: { STR_FREE(SG(request_info).path_translated); // php_request_shutdown实现在文件 php-5.6.26\main\main.c // --------------------------------------迭代执行“类似extension=test.so扩展”的 request_shutdown_func 函数 // --------------------------------------迭代执行“类似extension=test.so扩展”的 post_deactivate_func 函数 php_request_shutdown((void *) 0); { zend_bool report_memleaks; TSRMLS_FETCH(); report_memleaks = PG(report_memleaks); /* EG(opline_ptr) points into nirvana and therefore cannot be safely accessed * inside zend_executor callback functions. */ EG(opline_ptr) = NULL; EG(active_op_array) = NULL; php_deactivate_ticks(TSRMLS_C); /* 1. Call all possible shutdown functions registered with register_shutdown_function() */ if (PG(modules_activated)) zend_try { // 条件是: 模块是被激活的 php_call_shutdown_functions(TSRMLS_C); // 调用用户注册的关闭函数 } zend_end_try(); /* 2. Call all possible __destruct() functions */ zend_try { zend_call_destructors(TSRMLS_C); // 调用析构函数 } zend_end_try(); /* 3. Flush all output buffers */ zend_try { zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1; // 是否只需要头部 if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR && (size_t)PG(memory_limit) < zend_memory_usage(1 TSRMLS_CC) ) { send_buffer = 0; } if (!send_buffer) { // 是否发送缓存区 php_output_discard_all(TSRMLS_C); } else { php_output_end_all(TSRMLS_C); // 输出缓冲区的数据(头部数据 + body数据) } } zend_end_try(); /* 4. Reset max_execution_time (no longer executing php code after response sent) */ zend_try { zend_unset_timeout(TSRMLS_C); // 重置最大执行时间 } zend_end_try(); /* 5. Call all extensions RSHUTDOWN functions */ if (PG(modules_activated)) { // 条件是: 模块是被激活的 zend_deactivate_modules(TSRMLS_C); // -------------------------------------- 迭代执行“类似extension=test.so扩展”的 request_shutdown_func 函数 php_free_shutdown_functions(TSRMLS_C); // 释放用户注册的关闭函数 register_shutdown_function } /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */ zend_try { php_output_deactivate(TSRMLS_C); // 关闭输出层 } zend_end_try(); /* 7. Destroy super-globals */ zend_try { int i; for (i=0; i<NUM_TRACK_VARS; i++) { if (PG(http_globals)[i]) { // 销毁超级变量 如 $_POST、$_GET 等等 zval_ptr_dtor(&PG(http_globals)[i]); } } } zend_end_try(); /* 7.5 free last error information and temp dir */ // 释放错误信息 和 临时目录 if (PG(last_error_message)) { free(PG(last_error_message)); PG(last_error_message) = NULL; } if (PG(last_error_file)) { free(PG(last_error_file)); PG(last_error_file) = NULL; } php_shutdown_temporary_directory(); // 关闭临时目录 /* 7. Shutdown scanner/executor/compiler and restore ini entries */ // --------------------------------------迭代执行“类似zend_extension=test.so模块”的 deactivate 方法 等。。。 zend_deactivate(TSRMLS_C); // 关闭扫描器、执行器、编译器、复原 php.ini被修改的配置、迭代执行“类似zend_extension=test.so模块”的 deactivate 方法 等。。。 /* 8. Call all extensions post-RSHUTDOWN functions */ zend_try { zend_post_deactivate_modules(TSRMLS_C); // -------------------------------------- 迭代执行“类似extension=test.so扩展”的 post_deactivate_func 函数 } zend_end_try(); /* 9. SAPI related shutdown (free stuff) */ zend_try { sapi_deactivate(TSRMLS_C); // 释放 SG(request_info) 中的资源 } zend_end_try(); /* 9.5 free virtual CWD memory */ virtual_cwd_deactivate(TSRMLS_C); // 释放虚拟工作内存 /* 10. Destroy stream hashes */ zend_try { php_shutdown_stream_hashes(TSRMLS_C); } zend_end_try(); /* 11. Free Willy (here be crashes) */ // 关闭内存管理器 zend_try { shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0 TSRMLS_CC); } zend_end_try(); zend_interned_strings_restore(TSRMLS_C); /* 12. Reset max_execution_time */ // 重置最大执行时间 zend_try { zend_unset_timeout(TSRMLS_C); } zend_end_try(); #ifdef PHP_WIN32 if (PG(com_initialized)) { CoUninitialize(); PG(com_initialized) = 0; } #endif #ifdef HAVE_DTRACE DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method)); #endif /* HAVE_DTRACE */ } if (exit_status == 0) { exit_status = EG(exit_status); } if (free_query_string && SG(request_info).query_string) { free(SG(request_info).query_string); SG(request_info).query_string = NULL; } } ... /* only fastcgi will get here */ requests++; if (max_requests && (requests == max_requests)) { // 超过“最大请求数” fcgi_finish_request(request, 1); // 清除 request 对象 if (bindpath) { free(bindpath); } if (max_requests != 1) { /* no need to return exit_status of the last request */ exit_status = 0; } break; // } /* end of fastcgi loop */ // 至此处理完socket的请求 .... } .... // php_module_shutdown实现在文件 php-5.6.26\main\main.c php_module_shutdown(TSRMLS_C){ ... // zend_shutdown实现在文件 php-5.6.26\Zend\zend.c // --------------------------------------回收module_registry对象,迭代执行“类似extension=test.so扩展”的 module_shutdown_func 函数,通过hash的析构函数实现 // --------------------------------------迭代执行“类似zend_extension=test.so模块”的 shutdown 方法 zend_shutdown(TSRMLS_C); ... }; // 关闭 PHP 模块 }