php 启动过程 - sapi MSHUTDOWN 过程
php 启动过程 - sapi MSHUTDOWN 过程
概述
当服务器关闭时, 会走到 sapi MSHUTDOWN 过程
注册过程
本次内容是在
php 启动过程 - sapi MINIT 过程之后写的, 对于调用过程本次只做简单描述
- apache 加载 php 模块, apache 启动时调用注册的钩子函数 php_apache_server_startup
- php_apache_server_startup 中使用 apr_pool_cleanup_register 函数注册模块关闭函数 php_apache_server_shutdown
MSHUTDOWN 调用过程
调用 php_apache_server_shutdown
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_flush
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 引擎运行过程中产生的数据以及结构
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);
}
- 其中, zend_shutdown_extensions 会调用每个扩展的 shutdown 函数
调用 UNREGISTER_INI_ENTRIES, 注销 ini_entries
调用 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 输出关闭
- 全局变量以及结构
- 垃圾回收机制
php 启动过程 - sapi MSHUTDOWN 过程的更多相关文章
- php 启动过程 - sapi MINIT 过程
php 启动过程 - sapi MINIT 过程 sapi 概念 sapi 是 php 的应用编程接口, server 端接收请求通过 sapi 接口层交给 php 处理 不同的 server 端底层 ...
- php 启动过程 - reqeust RSHUTDOWN 过程
php 启动过程 - reqeust RSHUTDOWN 过程 概述 request RSHUTDOWN 过程在请求结束后调用 调用触发 同 request RINIT 过程一样, 先是用 apach ...
- php 启动过程 - reqeust RINIT 过程
php 启动过程 - reqeust RINIT 过程 概述 apache 接收到请求之后, 交给 php 处理 php 模块在接收到请求后, 会对请求进行初始化, 及 RINIT 过程 调用触发 a ...
- SpringBoot IoC启动流程、初始化过程及Bean生命周期各个阶段的作用
目录 SpringBoot IoC启动流程.初始化过程及Bean生命周期各个阶段的作用 简述 首先明确IoC容器是啥 准备-SpringApplication的实例化 启动-SpringApplica ...
- 第三次作业(1) Visual Studio程序安装过程和练习过程
Visual Studio程序安装过程和练习过程 第一步 首先要在网上找一个VS2013的安装包,之后我安装在D盘上,C盘上也需要有5.2G空间,勾选相应的选项,才能继续安装. 安装的过程很漫长,接近 ...
- Atitit. 软件开发中的管理哲学--一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
Atitit. 软件开发中的管理哲学--一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向 1. 一个伟大的事业必然是过程导向为主 1 1.1. 过程的执行情况(有明确的执行手册及标准) ...
- VScript 函数调用的两种分类:Sub过程和Function过程
来源:http://soft.zdnet.com.cn/software_zone/2007/0925/523318.shtml 在 VBScript 中,过程被分为两类:Sub 过程和 Functi ...
- Oracle数据库体系结构、启动过程、关闭过程
一.Oracle数据库体系结构体系结构由下面组件组成:1.Oracle服务器(Server):由数据库实例和数据库文件组成,另外在用户建立与服务器的连接时启动服务器进程并分配PGA(程序全局区) (1 ...
- iOS开发实践:一个类微博客户端从启动到与用户交互的过程
本文基于数据字典和数据流图两种工具讲述一个完整微博客户端的实现.数据字典和数据流图都可以用来表达线程的执行流程,同时定义了需要的类,是进一步设计类的基础. 数据字典实际上是一张表,表的第一个字段是程序 ...
随机推荐
- maven新建的项目,不自动引入依赖包
1.检查repository的目录是不是纯英文. 2.重新下载一次repository. 如果解决了问题,那么原因就是前面在加载repository的时候,因为断网导致了下载的包有误,无法被ecl ...
- Search a 2D Matrix leetcode
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- wemall软件交易平台微信图文编辑器部分代码分享
wemall软件交易平台微信图文编辑器部分代码,可下载: controller.php <?php date_default_timezone_set("Asia/chongqing& ...
- 1583: [Usaco2009 Mar]Moon Mooing 哞哞叫
1583: [Usaco2009 Mar]Moon Mooing 哞哞叫 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 244 Solved: 126 ...
- 1709: [Usaco2007 Oct]Super Paintball超级弹珠
1709: [Usaco2007 Oct]Super Paintball超级弹珠 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 339 Solved: ...
- 九度OJ题目1443:Tr A (JAVA)
题目描述: A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. 输入: 数据的第一行是一个T,表示有T组数据. 每组数据的第一行有n(2 <= n & ...
- SPM HW1 A project
项目分析 --民航航班异常轨迹可视分析 最近完成的一个项目是一个可视化大作业--民航航班异常轨迹可视分析.要求利用已给的8G飞机的飞行记录数据,将飞机的飞行轨迹在浏览器中进行飞行轨迹高维可视化以及对异 ...
- C — 对C语言的认识
有趣的C语言代码 看一下这段代码输出的是什么 #include <stdio.h> int main() { ; printf("%d\n", printf(" ...
- intellij idea打jar包时的注意事项
intellij idea项目在打包maven项目时,数据路径很容易出现问题.在IDE内直接运行不会报错,但打成jar包运行就会报错. intellij打包的几种方式:http://www.cnblo ...
- 在windows上缓存git 密码
缓存git密码 一搜索 大部分都是在linux上的 . git config --global credential.helper cache 但在windows上pull或者push会报如下错误: ...