PHP內核之Apache的PHP模塊啓動

首先,我們必須知道所有的apache module都必須是這個結構體,其定義結構如下(以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 */
	/* 上面4項都是定義httpd.conf中命令的作用的 */
	php_dir_cmds,			/* command apr_table_t */ * 定義在httpd.conf中添加的命令,和各命令的處理函數 *//
	php_ap2_register_hook	/* register hooks */ /* hooks,定義什麼時候執行我們這個 module的相關函數 */
};

STANDARD20_MODULE_STUFF這個宏是必須的,這個宏在經過擴展以後,可以爲編譯後的模塊載入服務器構建提供版本信息,

在PHP的模塊中,

create_php_config函數創建目錄配置結構,

merge_php_config合併目錄配置結構,

php_dir_cmds函數爲模塊配置相關指令,

php_ap2_register_hook 註冊模塊的鉤子程序,

在這裏主要關注的是php_ap2_register_hook.這裏定義的一些回調方法,會在Apache啓動的時候直接調用。 

查看php-5.5.12/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);
}


其中 

pre_config,  post_config, child_init 是啓動掛鉤,在服務器啓動時調用
handler是請求掛鉤,在服務器處理請求時調用


其中

在 post_config 掛鉤中啓動php  
post_config通過php_apache_server_startup函數實現, 


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_module_startup函數,這個函數會初始化若干全局變量,若干常量,Zend引擎和核心組件,解析php.ini,全局操作函數,靜態模塊和共享模塊(MINIT),同時還會禁用一些函數和類

這個函數具體介紹可以查看前一篇博文 PHP內核之SAPI:Apache2 SAPI分析

這就完成從apache啓動之後,至PHP的初始化和環境準備了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章