php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点

 

模块种类(两种)
    类型一: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 模块
    }

 

转载于:https://www.cnblogs.com/xiaoyaogege/p/8628935.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值