当服务器关闭时, 会走到 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 输出关闭
- 全局变量以及结构
- 垃圾回收机制