模块种类(两种)
类型一: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, ){
....
// 启动zend引擎(创建“全局函数表”、“全局类表”、“全局常量表”、“模块注册表”......)
zend_startup(&zuf, NULL TSRMLS_CC); // !!!!
...
// 注册常量
REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-, 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) - , 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, , message, arg);
{
int message;
void *arg; if (!extension->message_handler || num_args!=) {
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-])) {
spprintf(&libpath, , "%s%s", extension_dir, filename);
} else {
spprintf(&libpath, , "%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) >= ) { // 接受到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, ); // 回收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) = ;
SG(request_info).no_headers = ;
} ...
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) = ;
if (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, , prepend_file_p) == SUCCESS) {
CG(start_lineno) = orig_start_lineno;
retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, , 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, , prepend_file_p, primary_file, append_file_p) == SUCCESS); // 执行primary_file的php脚本
{
...
va_start(files, file_count);
for (i = ; i < file_count; i++) { //
file_handle = va_arg(files, zend_file_handle *); // 获取文件名(前置文件、主文件、后置文件)
if (!file_handle) {
continue;
} if (orig_interactive) {
if (file_handle->filename[] != '-' || file_handle->filename[]) {
CG(interactive) = ;
} else {
CG(interactive) = ;
}
} // 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=;
} 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) = ; // 是否处于汇编状态
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, TSRMLS_CC); // 返回
CG(in_compilation) = original_in_compilation; // 还原现场
if (compiler_result != ) { /* parser error */
zend_bailout();
}
compilation_successful=; // 汇编成功
} 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( 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 = ;
zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path) + , (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, 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 () {
zend_vm_enter:
execute_data = i_create_execute_data_from_op_array(EG(active_op_array), TSRMLS_CC);
} ... while () {
int ret;
#ifdef ZEND_WIN32
if (EG(timed_out)) {
zend_timeout();
}
#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();
}
} } > ) { // execute_data.opline->handler(execute_data TSRMLS_CC) // 调用“opcode对应的处理函数”
switch (ret) {
case :
EG(in_execution) = original_in_execution; // 还原现场
return;
case :
goto zend_vm_enter; // 进入虚拟机
break;
case :
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[], *retval2, *old_exception;
old_exception = EG(exception);
EG(exception) = NULL;
params[] = &old_exception;
orig_user_exception_handler = EG(user_exception_handler);
if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, , params, , 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 *) );
{
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 ? : ; // 是否只需要头部 if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR &&
(size_t)PG(memory_limit) < zend_memory_usage( TSRMLS_CC)
) {
send_buffer = ;
} 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=; 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, 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) = ;
}
#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 == ) {
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, ); // 清除 request 对象
if (bindpath) {
free(bindpath);
}
if (max_requests != ) {
/* no need to return exit_status of the last request */
exit_status = ;
}
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 模块
}

php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点的更多相关文章

  1. php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数

    // opcode处理器 --- ZEND_DO_FCALL_SPEC_CONST_HANDLER实现在 php-5.6.26\Zend\zend_vm_execute.h static int ZE ...

  2. php-5.6.26源代码 - 扩展模块的加载、注册

    // main实现在文件 php-5.6.26\sapi\cgi\cgi_main.c int main(int argc, char *argv[]) { .... cgi_sapi_module- ...

  3. php-5.6.26源代码 - hash存储结构 - 添加

    添加 , (void *)module, sizeof(zend_module_entry), (void**)&module_ptr){ // zend_hash_add 定义在文件“php ...

  4. php-5.6.26源代码 - hash存储结构 - 初始化

    初始化 有指定析构函数,在销毁hash的时候会调用,如:“类似extension=test.so扩展”也是存放在HashTable中的,“类似extension=test.so扩展”的module_s ...

  5. php-5.6.26源代码 - hash存储结构 - hash算法

    // zend_inline_hash_func 实现在文件“php-5.6.26\Zend\zend_hash.h” h = zend_inline_hash_func(arKey, nKeyLen ...

  6. php-7.2.3源代码和php-5.6.26源代码摘录,对比 “汇编php文件”和“执行opcode代码”

    php-7.2.3 在“汇编php文件”和“执行opcode代码”上做了大量改变php-5.6.26 没见到支持抽象语法树的相关代码,php-7.2.3 见到支持抽象语法树的相关代码php-5.6.2 ...

  7. php-5.6.26源代码 - opcode处理器的注入

    .初始化 opcode处理器列表 // main实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” int main(int argc, char *argv[]) { if ...

  8. php-5.6.26源代码 - opcode列表

    文件 php-5.6.26/Zend/zend_vm_opcodes.h #ifndef ZEND_VM_OPCODES_H #define ZEND_VM_OPCODES_H BEGIN_EXTER ...

  9. php-5.6.26源代码 - opcode执行

    文件 php-5.6.26/Zend/zend_vm_execute.h ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS ...

随机推荐

  1. springmvc实现文件下载到Android手机设备pda端

    1:首先要添加相关得jar文件,在pom.xml中 <dependency> <groupId>commons-fileupload</groupId> <a ...

  2. Android基础Activity篇——Menu

    1.创建一个menu 在res目录右击-->new-->Drirectory,创建menu,然后右击menu-->new-->Menu resource file 创建main ...

  3. android里的继承浅析

    先看一段代码: abstract class A{ public A(){ this.print(); } public abstract void print(); } class B extend ...

  4. centreon-engine 性能调优

    http://documentation.centreon.com/docs/centreon-engine/en/latest/user/configuration/best_practice.ht ...

  5. 2013应届毕业生各大IT公司待遇整理汇总篇(转)

    不管是应届毕业生还是职场中人,在找工作时都必然会对待遇十分关注,而通常都是面试到最后几轮才知道公司给出的待遇.如果我们事先就了解大概行情,那么就会在面试之前进行比较,筛选出几个心仪的公司,这样才能集中 ...

  6. RabbitMQ的用户管理方法

    1. 用户管理用户管理包括增加用户,删除用户,查看用户列表,修改用户密码.相应的命令 (1) 新增一个用户 rabbitmqctl  add_user  Username  Password (2) ...

  7. yum 源搭建

    RHEL系统部署网络yum源 配置网络yum源 RHEL系统本身光盘做成的yum源所提供的软件包有限,在实际使用过程中经常会出现缺包的现象,本文中以CentOS源作为替代,CentOS的软件包和RHE ...

  8. 前端js限制上传文件类型及大小(1)

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  9. HDU(1166),线段树模板,单点更新,区间总和

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 第一次做线段树,帆哥的一句话,我记下来了,其实,线段树就是一种处理数据查询和更新的手段. 然后, ...

  10. 动态数组第k小,Poj(1442)

    题目链接:http://poj.org/problem?id=1442 本来想复制一下,然后直接sort,结果T了. 在网上看了一下,有用两个队列做的,想了半天,没看懂什么意思.后来模拟一边,总算是懂 ...