当前位置: 首页 > 工具软件 > plog(PHP) > 使用案例 >

apache启动php模块,APache的PHP模块启动

单于善
2023-12-01

首先,了解一下每个Apache模块都会输出一个模块数据结构,其定义结构如下(以PHP模块为例):

AP_MODULE_DECLARE_DATA module php5_module = {

STANDARD20_MODULE_STUFF,

create_php_config, /* create per-directory config structure */

merge_php_config, /* merge per-directory config structures */

NULL, /* create per-server config structure */

NULL, /* merge per-server config structures */

php_dir_cmds, /* command apr_table_t */

php_ap2_register_hook /* register hooks */

};

STANDARD20_MODULE_STUFF这个宏是必须的,这个宏在经过扩展以后,可以为编译后的模块载入服务器构建提供版本信息,在PHP的模块中,create_php_config函数创建目录配置结构,,merge_php_config合并目录配置结构,php_dir_cmds函数为模块配置相关指令,php_ap2_register_hook 注册模块的钩子程序,对这个结构体会在apache的模块中专门说明,在这里主要关注的是php_ap2_register_hook.这里定义的一些回调方法,会在Apache启动的时候直接调用。

php_ap2_register_hook函数的实现在源码sapi/apache2handler/sapi_apache2.c文件中:

void php_ap2_register_hook(apr_pool_t *p)

{

ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);

ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);

ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);

ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);

}

php_apache_server_startup函数也在同一个文件里面实现:

static int

php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)

{

void *data = NULL;

const char *userdata_key = "apache2hook_post_config";

/* Apache will load, unload and then reload a DSO module. This

* prevents us from starting PHP until the second load. */

apr_pool_userdata_get(&data, userdata_key, s->process->pool);

if (data == NULL) {

/* We must use set() here and *not* setn(), otherwise the

* static string pointed to by userdata_key will be mapped

* to a different location when the DSO is reloaded and the

* pointers won't match, causing get() to return NULL when

* we expected it to return non-NULL. */

apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);

return OK;

}

/* Set up our overridden path. */

if (apache2_php_ini_path_override) {

apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;

}

#ifdef ZTS

tsrm_startup(1, 1, 0, NULL);

#endif

sapi_startup(&apache2_sapi_module);

apache2_sapi_module.startup(&apache2_sapi_module);

apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);

php_apache_add_version(pconf);

return OK;

}在这个函数里会调用apache2_sapi_module.startup函数,而这个函数在前一篇博文

PHP内核-Apache2的SAPI 可以看到,它最终调用的是php_module_startup函数,

该函数在PHP的主要文件main/main.c文件中:

int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)

{

zend_utility_functions zuf;

zend_utility_values zuv;

int module_number=0; /* for REGISTER_INI_ENTRIES() */

char *php_os;

#ifdef ZTS

zend_executor_globals *executor_globals;

void ***tsrm_ls;

php_core_globals *core_globals;

#endif

#if defined(PHP_WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))

WORD wVersionRequested = MAKEWORD(2, 0);

WSADATA wsaData;

#endif

....................

php_ini_register_extensions(TSRMLS_C);

zend_startup_modules(TSRMLS_C);

/* disable certain classes and functions as requested by php.ini */

php_disable_functions(TSRMLS_C);

php_disable_classes(TSRMLS_C);

/* start Zend extensions */

zend_startup_extensions();

#ifdef ZTS

zend_post_startup(TSRMLS_C);

#endif

module_initialized = 1;

sapi_deactivate(TSRMLS_C);

module_startup = 0;

shutdown_memory_manager(1, 0 TSRMLS_CC);

/* we're done */

return SUCCESS;

}这时会对PHP做一些环境初始化,如:php_init_config会读取php.ini文件,根据这个文件的配置,初始化PHP的环境及控制变量。

这就完成从apache启动之后,至PHP的初始化和环境准备了。

 类似资料: