学习PHP底层,咱们来看看PHP的工作原理与生命周期
Posted PHP自学中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习PHP底层,咱们来看看PHP的工作原理与生命周期相关的知识,希望对你有一定的参考价值。
文章来自:https://blog.csdn.net/weixin_33904756/article/details/88857180
点击加入:
技术交流微信群
我们在学习中单枪匹马,还不如一次短短的交流,你可以在别人吸取各种学习经验。 学习方法以及学习技巧,所以,学习与交流少不了一个圈子,提升你的学习技能。 请点击加技术群:PHP自学中心交流群
视频教程分享
1 Linux从零入门实战-2019年七月Z线
公众号里回复:08250023
2 Git版本管理视频教程
公众号里回复:20190102
3 web前端视频教程(基础+中级+高级)
公众号里回复:20181226
4 Laravel5.x底层实战兼核心源码解析
链接:http://www.mano100.cn/thread-344-1-1.html
5 由浅入深析Thinkphp5和ThinkPHP6底层源码
链接:http://www.mano100.cn/thread-1-1-1.html
6 全方位深度剖析PHP7底层源码(完整版)
链接:http://www.mano100.cn/thread-93-1-1.html
精选文章正文
php是一门适用于web开发的动态语言,它可以说是一个用C语言实现的包含大量组件的软件框架。那么,php是如何工作的呢?它的生命周期是怎么样的呢?
表层分析
php是以请求/响应为周期运行服务端应用程序,当请求进入应用程序,流程如下:
php的每一个请求都会重复以上的交互。
底层分析
php的运行模式有两种:web模式和cli模式。无论是哪种公众模式,php的工作原理都是一样的,都是作为一种SAPI运行。
首先,认识下SAPI是什么?
Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口。
Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离。
PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
常见的SAPI有cli、cgi、php-fpm以及各服务具体的sapi。
生命周期
在php的生命周期中,有4个关键调用:
以nginx服务器为例,在web模式下,生命周期流程如下:
SAPI运行PHP都经过下面几个阶段:
1、模块初始化阶段(module init)
这个阶段主要进行PHP框架和Zend引擎的初始化操作。该阶段的入口函数为php_module_startup()
。
这个阶段一般只在SAPI启动时执行一次,对于Fpm而言,就是在Fpm的master
进程启动时执行的。
该阶段的几个主要处理如下:
激活SAPI:
sapi_activate()
,初始化请求信息SG(request_info
)、设置读取POST请求的handle等。启动PHP输出:
php_output_startup()
初始化垃圾回收器:
gc_globals_ctor()
,并分配zend_gc_globals
内存。启动Zend引擎:
zend_startup()
,主要操作包括
1 启动内存池 start_memory_manager()
2 设置一些util函数句柄,如zend_error_cb
、zend_pringf````、
zend_write```等。
3 设置Zend虚拟机编译、执行器的函数句柄zend_compile_file
、zend_execute_ex
、垃圾回收函数句柄gc_collect_cycles
4 分配函数符号表 方法符号表(function_table
)、类符号表(class_table
)、常量符号表(zend_constants
)等,如果是多线程的话,还会分配编译器、执行器的全局变量
5 注册Zend核心扩展:zend_startup_builtin_funtions()
,这个扩展是内核提供的,该过程将注册Zend核心扩展提供的函数,如strlen
、define
、func_get_args
、class_exists
等。
6 注册Zend定义的标准常量:zend_register_standard_constants()
,比如E_ERROR
、E_WARNING
、E_ALL
、TRUE
、FALSE
等。
7 注册$GLOBALS
超全局变量的获取handle
。
8 分配php.ini配置的存储符号表 EG(ini_directives
)。
注册PHP定义的常量:
PHP_VERSION
、PHP_ZTS
、PHP_SAPI
等。解析php.ini:解析完成后所有的php.ini配置保存在
configuration_hash
哈希表中。映射PHP、Zend核心的php.ini配置:根据解析出的php.ini,获取对应的配置值,将最终的配置插入EG(ini_directives)哈希表。
注册用于获取
$_GET
、$_POST
、$_COOKIE
、$_SERVER
、$_ENV
、$_REQUEST
、$_FILES
变量的handle
。注册静态编译的扩展:
php_register_internal_extensions_func()
。注册动态加载的扩展:
php_init_register_extensions()
,将php.ini中配置的扩展加载到PHP中。回调各扩展定义的
module startup
钩子函数,即通过PHP_MINIT_FUNCTION()
定义的函数。注册php.ini中禁用的函数、类:
disable_funstions
、disable_classes
。
2、请求初始化阶段(request init)
当一个页面请求发生时,在请求处理前都会经历的一个阶段。对于fpm而言,是在worker进程accept一个请求并读取、解析完请求数据后的一个阶段。
在这个阶段内,SAPI层将控制权交给PHP层,PHP初始化本次请求执行脚本所需的环境变量。
该阶段的处理函数为php_request_startup()
。主要处理有以下几个:
(1)激活输出:php_output_activate()
(2)激活Zend引擎:zend_activate()
,主要操作有
(2.1)重置垃圾回收器:gc_reset()
(2.2)初始化编译器:ini_compiler()
(2.3)初始化执行器:ini_exexutor()
,将 EG(function_table
)和 EG(class_table
)分别执行 CG(function_table
)和CG(class_table
)。
(2.4)初始化全局变量符号表 EG(symbol_table
)、include过的文件符号表 EG(included_files
)
(2.5)初始化词法扫描器:sapi_activate()
(3)激活SAPI:sapi_activate()
(4)回调个扩展定义的request startup钩子函数:zend_activate_modules()
3、php脚本执行阶段(execute sccript)
(1)该阶段包括PHP代码的编译、执行两个核心阶段,这也是Zend引擎最重要的功能。
(2)在编译阶段,PHP脚本将经历从PHP源代码到抽象语法树,再到opline指令的转化过程,最终生成的opline指令就是Zend引擎可识别的执行指令,这些指令被执行器执行,这就是PHP代码解释执行的过程。
该阶段入口函数为php_execute_script()
。
4、请求结束阶段(request shutdown)
(1)该阶段将flush输出内容、发送HTTP
应答header
头、清理局部变量、关闭编译器、关闭执行器等。
(2)另外,在该阶段将回调各扩展的request shutdown
钩子函数。
(3)该阶段与请求初始化阶段操作是相反的。
5、模块关闭阶段(module shutdown)
该阶段在SAPI关闭时执行,与模块初始化阶段对应,这个阶段主要是进行资源的清理、php各模块的关闭操作,同时,将回调各扩展的module shutdown
钩子函数。
这是发生在所有请求都已经结束之后,例如关闭fpm的操作。(这个是对于CGI和CLI等SAPI,没有“下一个请求”,所以SAPI立刻开始关闭。)
注:根据不同SAPI的实现,各阶段的执行情况会有一些差异,比如命令行模式下,每次执行一个脚本都会完成的经历这些阶段。
而FastCgi模式下则在启动时执行一次模块初始化,然后各个请求只经历请求初始化,脚本执行,请求关闭几个阶段,在SAPI关闭时,才经历模块关闭阶段。
以上是本文的全部内容,希望对大家的学习有帮助,也希望大家多多支持 php自学中心 ,学习与交流少不了一个圈子,点击加技术群:
以上是关于学习PHP底层,咱们来看看PHP的工作原理与生命周期的主要内容,如果未能解决你的问题,请参考以下文章