php-5.6.26源代码 - 扩展模块的加载、注册
// main实现在文件 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_extensions 中(php.ini中以zend_extension开头的配置,如zend_extension=test.so) zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC); { // php_ini_register_extensions实现在文件 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实现在文件 php-5.6.26\Zend\zend_extensions.c zend_load_extension(filename); // 把扩展添加到链表zend_extensions中 { int zend_load_extension(const char *path) { #if ZEND_EXTENSIONS_SUPPORT DL_HANDLE handle; zend_extension *new_extension; zend_extension_version_info *extension_version_info; handle = DL_LOAD(path); // 加载动态链接库 if (!handle) { #ifndef ZEND_WIN32 fprintf(stderr, "Failed loading %s: %s\n", path, DL_ERROR()); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif #else fprintf(stderr, "Failed loading %s\n", path); #endif return FAILURE; } 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"); } if (!extension_version_info || !new_extension) { fprintf(stderr, "%s doesn't appear to be a valid Zend extension\n", path); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif DL_UNLOAD(handle); return FAILURE; } /* allow extension to proclaim compatibility with any Zend version */ // 扩展的版本信息 if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) { if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) { fprintf(stderr, "%s requires Zend Engine API version %d.\n" "The Zend Engine API version %d which is installed, is outdated.\n\n", new_extension->name, extension_version_info->zend_extension_api_no, ZEND_EXTENSION_API_NO); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif DL_UNLOAD(handle); return FAILURE; } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) { fprintf(stderr, "%s requires Zend Engine API version %d.\n" "The Zend Engine API version %d which is installed, is newer.\n" "Contact %s at %s for a later version of %s.\n\n", new_extension->name, // 扩展名称 extension_version_info->zend_extension_api_no, ZEND_EXTENSION_API_NO, new_extension->author, // 扩展作者 new_extension->URL, // 扩展地址 new_extension->name); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif DL_UNLOAD(handle); return FAILURE; } } else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) && (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) { fprintf(stderr, "Cannot load %s - it was built with configuration %s, whereas running engine is %s\n", new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif DL_UNLOAD(handle); return FAILURE; } else if (zend_get_extension(new_extension->name)) { fprintf(stderr, "Cannot load %s - extension already loaded\n", new_extension->name); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif DL_UNLOAD(handle); return FAILURE; } return zend_register_extension(new_extension, handle); // !!!注册扩展信息,并迭代执行“类似zend_extension=test.so模块”的 message_handler 方法 #else fprintf(stderr, "Extensions are not supported on this platform.\n"); /* See http://support.microsoft.com/kb/190351 */ #ifdef PHP_WIN32 fflush(stderr); #endif return FAILURE; #endif } } } 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); } } } // 加载extension_dir用户扩展模块,并把模块信息添加到模块注册表module_registry中 (php.ini中以extension开头的配置,如extension=test.so) zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC); { // php_load_php_extension_cb 实现在文件 php-5.6.26\main\php_ini.c static void php_load_php_extension_cb(void *arg TSRMLS_DC) { #ifdef HAVE_LIBDL // php_load_extension 实现在文件 php-5.6.26\ext\standard\dl.c php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0 TSRMLS_CC); #endif { void *handle; char *libpath; zend_module_entry *module_entry; zend_module_entry *(*get_module)(void); int error_type; char *extension_dir; if (type == MODULE_PERSISTENT) { extension_dir = INI_STR("extension_dir"); // 扩展目录 } else { extension_dir = PG(extension_dir); } if (type == MODULE_TEMPORARY) { error_type = E_WARNING; } else { error_type = E_CORE_WARNING; } /* Check if passed filename contains directory separators */ if (strchr(filename, '/') != NULL || strchr(filename, DEFAULT_SLASH) != NULL) { /* Passing modules with full path is not supported for dynamically loaded extensions */ if (type == MODULE_TEMPORARY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Temporary module name should contain only filename"); return FAILURE; } libpath = estrdup(filename); } else if (extension_dir && extension_dir[0]) { int extension_dir_len = strlen(extension_dir); if (IS_SLASH(extension_dir[extension_dir_len-1])) { spprintf(&libpath, 0, "%s%s", extension_dir, filename); /* SAFE */ } else { spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); /* SAFE */ } } else { return FAILURE; /* Not full path given or extension_dir is not set */ } /* load dynamic symbol */ handle = DL_LOAD(libpath); // 加载test.so文件 if (!handle) { #if PHP_WIN32 char *err = GET_DL_ERROR(); if (err && (*err != "")) { php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, err); LocalFree(err); } else { php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, "Unknown reason"); } #else php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, GET_DL_ERROR()); GET_DL_ERROR(); /* free the buffer storing the error */ #endif efree(libpath); return FAILURE; } efree(libpath); get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); // 模块的固定入口 /* Some OS prepend _ to symbol names while their dynamic linker * does not do that automatically. Thus we check manually for * _get_module. */ if (!get_module) { get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module"); } if (!get_module) { if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) { DL_UNLOAD(handle); php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename); return FAILURE; } DL_UNLOAD(handle); php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (maybe not a PHP library) '%s'", filename); return FAILURE; } module_entry = get_module(); // 取得模块信息 if (module_entry->zend_api != ZEND_MODULE_API_NO) { /* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */ struct pre_4_1_0_module_entry { char *name; 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); int (*global_startup_func)(void); int (*global_shutdown_func)(void); int globals_id; int module_started; unsigned char type; void *handle; int module_number; unsigned char zend_debug; unsigned char zts; unsigned int zend_api; }; const char *name; int zend_api; if ((((struct pre_4_1_0_module_entry *)module_entry)->zend_api > 20000000) && (((struct pre_4_1_0_module_entry *)module_entry)->zend_api < 20010901) ) { name = ((struct pre_4_1_0_module_entry *)module_entry)->name; zend_api = ((struct pre_4_1_0_module_entry *)module_entry)->zend_api; } else { name = module_entry->name; zend_api = module_entry->zend_api; } php_error_docref(NULL TSRMLS_CC, error_type, "%s: Unable to initialize module\n" "Module compiled with module API=%d\n" "PHP compiled with module API=%d\n" "These options need to match\n", name, zend_api, ZEND_MODULE_API_NO); DL_UNLOAD(handle); return FAILURE; } if(strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) { php_error_docref(NULL TSRMLS_CC, error_type, "%s: Unable to initialize module\n" "Module compiled with build ID=%s\n" "PHP compiled with build ID=%s\n" "These options need to match\n", module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID); DL_UNLOAD(handle); return FAILURE; } module_entry->type = type; module_entry->module_number = zend_next_free_module(); module_entry->handle = handle; if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)){ // zend_register_module_ex 实现在文件 php-5.6.26\Zend\zend_API.c ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ { int name_len; char *lcname; zend_module_entry *module_ptr; if (!module) { return NULL; } #if 0 zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif /* Check module dependencies */ if (module->deps) { // 模块依赖 const zend_module_dep *dep = module->deps; while (dep->name) { // 依赖名称 if (dep->type == MODULE_DEP_CONFLICTS) { name_len = strlen(dep->name); lcname = zend_str_tolower_dup(dep->name, name_len); if (zend_hash_exists(&module_registry, lcname, name_len+1)) { // 模块是否已经注册 efree(lcname); /* TODO: Check version relationship */ zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name); return NULL; } efree(lcname); } ++dep; } } name_len = strlen(module->name); lcname = zend_str_tolower_dup(module->name, name_len); if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) { // 添加模块信息到“模块注册表module_registry” zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name); efree(lcname); return NULL; } efree(lcname); module = module_ptr; EG(current_module) = module; // 当前模块 // 注册扩展模块的函数 if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC){ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ { const zend_function_entry *ptr = functions; // 要注册的“模块的函数列表” zend_function function, *reg_function; // zend_function联合体 zend_internal_function *internal_function = (zend_internal_function *)&function; // internal_function描述扩展模块中每个函数的信息 int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL; const char *lowercase_name; int fname_len; const char *lc_class_name = NULL; int class_name_len = 0; zend_ulong hash; if (type==MODULE_PERSISTENT) { error_type = E_CORE_WARNING; } else { error_type = E_WARNING; } if (!target_function_table) { // 如果没有指定target_function_table,那么默认填充到CG(v) target_function_table = CG(function_table); // !!! } internal_function->type = ZEND_INTERNAL_FUNCTION; // 函数类型 internal_function->module = EG(current_module); // 所属模块 if (scope) { class_name_len = strlen(scope->name); // 类名 if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) { ++lc_class_name; class_name_len -= (lc_class_name - scope->name); lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len); } else { lc_class_name = zend_str_tolower_dup(scope->name, class_name_len); } } while (ptr->fname) { // 函数名称 internal_function->handler = ptr->handler; // 函数指针,等价function->handler = ptr->handler; internal_function->function_name = (char*)ptr->fname; // 函数名 internal_function->scope = scope; // 函数的作用域 internal_function->prototype = NULL; if (ptr->flags) { if (!(ptr->flags & ZEND_ACC_PPP_MASK)) { if (ptr->flags != ZEND_ACC_DEPRECATED || scope) { zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname); } internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags; } else { internal_function->fn_flags = ptr->flags; } } else { internal_function->fn_flags = ZEND_ACC_PUBLIC; } if (ptr->arg_info) { // 函数的参数信息 zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info; internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1; internal_function->num_args = ptr->num_args; /* Currently you cannot denote that the function can accept less arguments than num_args */ if (info->required_num_args == -1) { internal_function->required_num_args = ptr->num_args; } else { internal_function->required_num_args = info->required_num_args; } if (info->return_reference) { internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE; } if (ptr->arg_info[ptr->num_args].is_variadic) { internal_function->fn_flags |= ZEND_ACC_VARIADIC; } } else { internal_function->arg_info = NULL; internal_function->num_args = 0; internal_function->required_num_args = 0; } if (ptr->flags & ZEND_ACC_ABSTRACT) { if (scope) { /* This is a class that must be abstract itself. Here we set the check info. */ scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) { /* Since the class is not an interface it needs to be declared as a abstract class. */ /* Since here we are handling internal functions only we can add the keyword flag. */ /* This time we set the flag for the keyword 'abstract'. */ scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } } if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) { zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname); } } else { if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) { efree((char*)lc_class_name); zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname); return FAILURE; } if (!internal_function->handler) { if (scope) { efree((char*)lc_class_name); } zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname); zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); return FAILURE; } } fname_len = strlen(ptr->fname); // 函数名称 lowercase_name = zend_new_interned_string(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC); hash = str_hash(lowercase_name, fname_len); // 生成hash值 // 注册函数到HashTable 类型的CG(function_table)中 if (zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, hash, &function, sizeof(zend_function), (void**)®_function) == FAILURE) { unload=1; str_efree(lowercase_name); break; } /* If types of arguments have to be checked */ if (reg_function->common.arg_info && reg_function->common.num_args) { int i; for (i = 0; i < reg_function->common.num_args; i++) { if (reg_function->common.arg_info[i].class_name || reg_function->common.arg_info[i].type_hint) { reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; break; } } } if (scope) { /* Look for ctor, dtor, clone * If it's an old-style constructor, store it only if we don't have * a constructor already. */ if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name, lc_class_name, class_name_len+1)) { ctor = reg_function; // 函数名是"类名" } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) { ctor = reg_function; // 函数名是"__construct" } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1)) { dtor = reg_function; // 函数名是"__destruct" if (internal_function->num_args) { zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname); } } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1)) { clone = reg_function; // 函数名是"__clone" } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) { __call = reg_function; } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1)) { __callstatic = reg_function; } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME) - 1)) { __tostring = reg_function; } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) { __get = reg_function; } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) { __set = reg_function; } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) { __unset = reg_function; } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) { __isset = reg_function; } else if ((fname_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1)) { __debugInfo = reg_function; } else { reg_function = NULL; } if (reg_function) { zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC); } } ptr++; count++; str_efree(lowercase_name); } if (unload) { /* before unloading, display all remaining bad function in the module */ if (scope) { efree((char*)lc_class_name); } while (ptr->fname) { fname_len = strlen(ptr->fname); lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len); if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) { zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname); } efree((char*)lowercase_name); ptr++; } zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); return FAILURE; } if (scope) { // 有指定作用域 scope->constructor = ctor; // 构造函数 scope->destructor = dtor; // 析构函数 scope->clone = clone; // clone函数 scope->__call = __call; // __call函数 scope->__callstatic = __callstatic; scope->__tostring = __tostring; scope->__get = __get; scope->__set = __set; scope->__unset = __unset; scope->__isset = __isset; scope->__debugInfo = __debugInfo; if (ctor) { ctor->common.fn_flags |= ZEND_ACC_CTOR; if (ctor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name); } ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (dtor) { dtor->common.fn_flags |= ZEND_ACC_DTOR; if (dtor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name); } dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (clone) { clone->common.fn_flags |= ZEND_ACC_CLONE; if (clone->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name); } clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__call) { if (__call->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name); } __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__callstatic) { if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) { zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name); } __callstatic->common.fn_flags |= ZEND_ACC_STATIC; } if (__tostring) { if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name); } __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__get) { if (__get->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name); } __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__set) { if (__set->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name); } __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__unset) { if (__unset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name); } __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__isset) { if (__isset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name); } __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__debugInfo) { if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __debugInfo->common.function_name); } } efree((char*)lc_class_name); } return SUCCESS; } }==FAILURE) { // 注册模块的函数到 CG(function_table) EG(current_module) = NULL; zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); return NULL; } EG(current_module) = NULL; return module; } } == NULL) { // 把模块信息添加到模块注册表module_registry中 DL_UNLOAD(handle); return FAILURE; } if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) { DL_UNLOAD(handle); return FAILURE; } if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) { if (module_entry->request_startup_func(type, module_entry->module_number TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, error_type, "Unable to initialize module '%s'", module_entry->name); DL_UNLOAD(handle); return FAILURE; } } return SUCCESS; } } } } ... } ... } ... } ... }