當服務器關閉時, 會走到 sapi MSHUTDOWN 過程php
本次內容是在
php 啓動過程 - sapi MINIT 過程
以後寫的, 對於調用過程本次只作簡單描述apache
調用 php_apache_server_shutdownapi
static apr_status_t php_apache_server_shutdown(void *tmp) { apache2_sapi_module.shutdown(&apache2_sapi_module); sapi_shutdown(); #ifdef ZTS tsrm_shutdown(); #endif return APR_SUCCESS; }
調用 apache2_sapi_module.shutdown, 其實是調用的 php_module_shutdown_wrapper 函數緩存
int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals) { TSRMLS_FETCH(); php_module_shutdown(TSRMLS_C); return SUCCESS; }
調用 php_module_shutdown 函數服務器
void php_module_shutdown(TSRMLS_D) { int module_number=0; /* for UNREGISTER_INI_ENTRIES() */ module_shutdown = 1; // 若模塊未初始化過, 直接返回 if (!module_initialized) { return; } // 省略 ... sapi_flush(TSRMLS_C); zend_shutdown(TSRMLS_C); php_shutdown_stream_wrappers(module_number TSRMLS_CC); UNREGISTER_INI_ENTRIES(); php_shutdown_config(); #ifndef ZTS zend_ini_shutdown(TSRMLS_C); shutdown_memory_manager(CG(unclean_shutdown), 1 TSRMLS_CC); #else zend_ini_global_shutdown(TSRMLS_C); #endif php_output_shutdown(); module_initialized = 0; #ifndef ZTS core_globals_dtor(&core_globals TSRMLS_CC); gc_globals_dtor(TSRMLS_C); #else ts_free_id(core_globals_id); #endif // 省略 ... }
調用 sapi_flush, 刷新 sapi 緩存數據, 實際調用的是 php_apache_sapi_flushapp
SAPI_API int sapi_flush(TSRMLS_D) { if (sapi_module.flush) { sapi_module.flush(SG(server_context)); return SUCCESS; } else { return FAILURE; } }
// 調用 php_apache_sapi_flush 函數 static void php_apache_sapi_flush(void *server_context) { // server_context php_struct *ctx; // apache 請求對象 request_rec *r; TSRMLS_FETCH(); // 省略 ... // sapi 發送響應頭信息 sapi_send_headers(TSRMLS_C); // 響應頭信息發送記錄 r->status = SG(sapi_headers).http_response_code; SG(headers_sent) = 1; if (ap_rflush(r) < 0 || r->connection->aborted) { php_handle_aborted_connection(); } }
php_struct 結構函數
// server_context 結構 typedef struct php_struct { int state; request_rec *r; apr_bucket_brigade *brigade; /* stat structure of the current file */ #if defined(NETWARE) && defined(CLIB_STAT_PATCH) struct stat_libc finfo; #else struct stat finfo; #endif // 是否在處理請求 int request_processed; // content_type char *content_type; } php_struct;
調用 zend_shutdown, 關閉 zend 引擎, 主要是關閉 zend 引擎運行過程當中產生的數據以及結構code
void zend_shutdown(TSRMLS_D) /* {{{ */ { #ifdef ZEND_SIGNALS zend_signal_shutdown(TSRMLS_C); #endif zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC); /* * 如下全部的事情都是清除以及釋放函數表, 類表, 常量表, 以及全局性的一些結構 * 其中 zend_shutdown_extensions 調用每一個擴展本身的 shutdown 函數 */ if (EG(active)) { zend_hash_reverse_apply(GLOBAL_FUNCTION_TABLE, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); zend_hash_reverse_apply(GLOBAL_CLASS_TABLE, (apply_func_t) zend_cleanup_user_class_data TSRMLS_CC); zend_cleanup_internal_classes(TSRMLS_C); zend_hash_reverse_apply(GLOBAL_FUNCTION_TABLE, (apply_func_t) clean_non_persistent_function_full TSRMLS_CC); zend_hash_reverse_apply(GLOBAL_CLASS_TABLE, (apply_func_t) clean_non_persistent_class_full TSRMLS_CC); } zend_destroy_modules(); zend_hash_destroy(GLOBAL_FUNCTION_TABLE); zend_hash_destroy(GLOBAL_CLASS_TABLE); zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); free(GLOBAL_AUTO_GLOBALS_TABLE); zend_shutdown_extensions(TSRMLS_C); free(zend_version_info); free(GLOBAL_FUNCTION_TABLE); free(GLOBAL_CLASS_TABLE); zend_hash_destroy(GLOBAL_CONSTANTS_TABLE); free(GLOBAL_CONSTANTS_TABLE); zend_shutdown_strtod(); #ifdef ZTS GLOBAL_FUNCTION_TABLE = NULL; GLOBAL_CLASS_TABLE = NULL; GLOBAL_AUTO_GLOBALS_TABLE = NULL; GLOBAL_CONSTANTS_TABLE = NULL; #endif zend_destroy_rsrc_list_dtors(); zend_interned_strings_dtor(TSRMLS_C); }
調用 UNREGISTER_INI_ENTRIES, 註銷 ini_entriesserver
調用 php_shutdown_config, 銷燬 php.ini 配置信息對象
int php_shutdown_config(void) { zend_hash_destroy(&configuration_hash); if (php_ini_opened_path) { free(php_ini_opened_path); php_ini_opened_path = NULL; } if (php_ini_scanned_files) { free(php_ini_scanned_files); php_ini_scanned_files = NULL; } return SUCCESS; }
銷燬 zend ini 信息
調用 php_output_shutdown, 關閉 output
PHPAPI void php_output_shutdown(void) { php_output_direct = php_output_stderr; zend_hash_destroy(&php_output_handler_aliases); zend_hash_destroy(&php_output_handler_conflicts); zend_hash_destroy(&php_output_handler_reverse_conflicts); }
釋放 core_globals
static void core_globals_dtor(php_core_globals *core_globals TSRMLS_DC) { if (core_globals->last_error_message) { free(core_globals->last_error_message); } if (core_globals->last_error_file) { free(core_globals->last_error_file); } if (core_globals->disable_functions) { free(core_globals->disable_functions); } if (core_globals->disable_classes) { free(core_globals->disable_classes); } if (core_globals->php_binary) { free(core_globals->php_binary); } php_shutdown_ticks(TSRMLS_C); }
釋放垃圾回收機制
sapi MSHUTDOWN 處理函數在 sapi MINIT 啓動過程當中註冊
當 sapi 關閉時觸發 MSHUTDOWN 過程
MSHUTDOWN 過程主要作了一下幾件事:
- 刷新並清空當前 sapi 的請求
- zend 引擎功能關閉, 釋放相關內存結構
- 註銷, 釋放, 清除 php 模塊相關結構
- ini_entry
- php.ini 配置信息
- zend_ini 信息
- 內存管理
- output 輸出關閉
- 全局變量以及結構
- 垃圾回收機制