PHP内核的学习–PHP生命周期
一切的开始: SAPI接口
SAPI(Server Application Programming Interface)指的是PHP具体应用的编程接口, 就像PC一样,无论安装哪些操作系统,只要满足了PC的接口规范都可以在PC上正常运行, PHP脚本要执行有很多种方式,通过Web服务器,或者直接在命令行下,也可以嵌入在其他程序中。
通常,我们使用Apache或者Nginx这类Web服务器来测试PHP脚本,或者在命令行下通过PHP解释器程序来执行。 脚本执行完后,Web服务器应答,浏览器显示应答信息,或者在命令行标准输出上显示内容。
我们很少关心PHP解释器在哪里。虽然通过Web服务器和命令行程序执行脚本看起来很不一样, 实际上它们的工作流程是一样的。命令行参数传递给PHP解释器要执行的脚本, 相当于通过url请求一个PHP页面。脚本执行完成后返回响应结果,只不过命令行的响应结果是显示在终端上。
脚本执行的开始都是以SAPI接口实现开始的。只是不同的SAPI接口实现会完成他们特定的工作, 例如Apache的mod_php SAPI实现需要初始化来&源gao@dai!ma.com搞$代^码%网搞gaodaima代码从Apache获取的一些信息,在输出内容是将内容返回给Apache, 其他的SAPI实现也类似。
下面几个小节将对一些常见的SAPI实现进行更为深入的介绍。
开始和结束
PHP开始执行以后会经过两个主要的阶段:处理请求之前的开始阶段和请求之后的结束阶段。 开始阶段有两个过程:第一个过程是模块初始化阶段(MINIT), 在整个SAPI生命周期内(例如Apache启动以后的整个生命周期内或者命令行程序整个执行过程中), 该过程只进行一次。第二个过程是模块激活阶段(RINIT),该过程发生在请求阶段, 例如通过url请求某个页面,则在每次请求之前都会进行模块激活(RINIT请求开始)。 例如PHP注册了一些扩展模块,则在MINIT阶段会回调所有模块的MINIT函数。 模块在这个阶段可以进行一些初始化工作,例如注册常量,定义模块使用的类等等。 模块在实现时可以通过如下宏来实现这些回调函数:
<span style="color: #000000">PHP_MINIT_FUNCTION(myphpextension){ </span><span style="color: #008000">//</span><span style="color: #008000"> 注册常量或者类等初始化操作</span> <span style="color: #0000ff">return</span><span style="color: #000000"> SUCCESS; }</span>
请求到达之后PHP初始化执行脚本的基本环境,例如创建一个执行环境,包括保存PHP运行过程中变量名称和值内容的符号表, 以及当前所有的函数以及类等信息的符号表。然后PHP会调用所有模块的RINIT函数, 在这个阶段各个模块也可以执行一些相关的操作,模块的RINIT函数和MINIT回调函数类似:
<span style="color: #000000">PHP_RINIT_FUNCTION(myphpextension){ </span><span style="color: #008000">//</span><span style="color: #008000"> 例如记录请求开始时间 </span><span style="color: #008000">//</span><span style="color: #008000"> 随后在请求结束的时候记录结束时间。这样我们就能够记录下处理请求所花费的时间了</span> <span style="color: #0000ff">return</span><span style="color: #000000"> SUCCESS; }</span>
请求处理完后就进入了结束阶段,一般脚本执行到末尾或者通过调用exit()或die()函数, PHP都将进入结束阶段。和开始阶段对应,结束阶段也分为两个环节,一个在请求结束后停用模块(RSHUTDOWN,对应RINIT), 一个在SAPI生命周期结束(Web服务器退出或者命令行脚本执行完毕退出)时关闭模块(MSHUTDOWN,对应MINIT)。
<span style="color: #000000">PHP_RSHUTDOWN_FUNCTION(myphpextension){ </span><span style="color: #008000">//</span><span style="color: #008000"> 例如记录请求结束时间,并把相应的信息写入到日至文件中。</span> <span style="color: #0000ff">return</span><span style="color: #000000"> SUCCESS; }</span>