// 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, ){
....
// 启动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_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-])) {
spprintf(&libpath, , "%s%s", extension_dir, filename);
} else {
spprintf(&libpath, , "%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, 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[]) {
int extension_dir_len = strlen(extension_dir); if (IS_SLASH(extension_dir[extension_dir_len-])) {
spprintf(&libpath, , "%s%s", extension_dir, filename); /* SAFE */
} else {
spprintf(&libpath, , "%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 > ) &&
(((struct pre_4_1_0_module_entry *)module_entry)->zend_api < )
) {
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+)) { // 模块是否已经注册
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+, (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=, unload=;
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 = ;
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+;
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 == -) {
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 = ;
internal_function->required_num_args = ;
}
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 + , 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+, hash, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
unload=;
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 = ; 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+)) {
ctor = reg_function; // 函数名是"类名"
} else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - )) {
ctor = reg_function; // 函数名是"__construct"
} else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - )) {
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)-) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - )) {
clone = reg_function; // 函数名是"__clone"
} else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - )) {
__call = reg_function;
} else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - )) {
__callstatic = reg_function;
} else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME) - )) {
__tostring = reg_function;
} else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - )) {
__get = reg_function;
} else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - )) {
__set = reg_function;
} else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - )) {
__unset = reg_function;
} else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - )) {
__isset = reg_function;
} else if ((fname_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-) && !memcmp(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME) - )) {
__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+)) {
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;
}
}
}
}
...
}
...
}
...
}
...
}

php-5.6.26源代码 - 扩展模块的加载、注册的更多相关文章

  1. ExtJs 通过分析源代码解决动态加载Controller的问题

    通过分析源代码解决动态加载Controller的问题 最近在研究ExtJs(4.2.0)的MVC开发模式,具体Extjs的MVC如何使用这里不解释,具体参见ExtJs的官方文档.这里要解决的问题是如何 ...

  2. AngularJS + ui-router + RequireJS异步加载注册controller/directive/filter/service

    一般情况下我们会将项目所用到的controller/directive/filter/sercive预先加载完再初始化AngularJS模块,但是当项目比较复杂的情况下,应该是打开对应的界面才加载对应 ...

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

    模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=t ...

  4. 《Entity Framework 6 Recipes》中文翻译系列 (26) ------ 第五章 加载实体和导航属性之延缓加载关联实体和在别的LINQ查询操作中使用Include()方法

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-7  在别的LINQ查询操作中使用Include()方法 问题 你有一个LINQ ...

  5. Spring IOC:BeanDefinition加载注册流程(转)

    BeanFactory接口体系 以DefaultListableBeanFactory为例梳理一下BeanFactory接口体系的细节 主要接口.抽象类的作用如下: BeanFactory(根据注册的 ...

  6. spring(四):IoC初始化流程&BeanDefinition加载注册

    ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml"); /** * * @par ...

  7. 关于WordPress中字体加载慢的问题解决方案(转)

    2016-04-15 最近发现Wordpress有时候加载的特别慢,于是就想办法找了下原因.之前听网上说是因为wordpress用的是Google的字体库,而且是每次都要加载,导致访问慢的,于是当时装 ...

  8. Inside Flask - flask 扩展加载过程

    Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ...

  9. Picasso解决 TextView加载html图片异步显示

    项目中有这样一个需求: textview加载一段 html标签 其中包含 "<Img url= " 图片异步展示 而且 根据图片的比例 宽度满屏展示. 思路: 重写textv ...

随机推荐

  1. html:option

    注意事项: (1):In HTML the <option> tag has no end tag.HTML中<option>标签不需要关闭.In XHTML the < ...

  2. 硬盘的基础知识-SSD

    硬盘有三类:HDD(机械硬盘),SSD(固态硬盘),HHD(混合硬盘) 原理: HDD:磁性碟片 SSD: 闪存颗粒 HHD:磁性碟片的基础上加上了闪存颗粒. 这里对HDD,HHD不加说明,只对SSD ...

  3. JDBC之Java连接mysql实现增删改查

    使用软件:mysql.eclipse 链接步骤: 1.注册驱动 2.创建一个连接对象 3.写sql语句 4.执行sql语句并返回一个结果或者结果集 5.关闭链接(一般就是connection.stat ...

  4. Socket网络通信之NIO

    Socket网络通信之NIO NIO:new io ,java1.4开始推出的可非阻塞IO. java.nio 包,可解决BIO阻塞的不足 但比BIO学习.使用复杂. 可以以阻塞.非阻塞两种方式工作. ...

  5. Ienumerable和Ienumerator的使用

    using UnityEngine; using System.Collections; public class TestCoroutine : MonoBehaviour { void Start ...

  6. AWS ELB Sticky Session有问题?别忘了AWSELB cookie

    我们的产品中有两个Module,分别部署在独立的Linux机器上,Module 1需要向Module 2发起Http请求来获得服务.由于Module 2有多台,因此我们会在Module 2前部署一台负 ...

  7. Struts2_Struts标签

    1.property <s:property value="username" /> 一般访问,访问ValueStack中的第一个username <s:prop ...

  8. php程序员发展建议

    2017PHP程序员的进阶之路 又是一年毕业季,可能会有好多毕业生即将进入开发这个圈子,踏上码农这个不归路.根据这些年在开发圈子总结的LNMP程序猿发展轨迹,结合个人经验体会,总结出很多程序员对未来的 ...

  9. Linux远程桌面(一)

    在机房折磨很久弄好的自己 Mark 一下.(测试环境rhel5.5) vnc 之独立服务配置 步骤一: (1)查看系统是否安装vnc服务(也可以在 系统-管理员-服务 里查看并勾选开机自启) # rp ...

  10. MSMQ学习笔记二——创建Message Queue队列

    一.创建Message Queue队列的主要流程 1.定义MQQUEUEPROPS 结构: 2.设置消息队列属性: 3.初始化MQQUEUEPROPS 结构: 4.调用MQCreateQueue创建队 ...