php执行的生命周期是怎样的?

php执行的生命周期是怎样的?

一切的开始: SAPI接口

SAPI(Server Application Programming Interface)指的是PHP具体应用的编程接口,就像PC一样,无论安装哪些操作系统,只要满足了PC的接口规范都可以在PC上正常运行。

脚本执行的开始都是以SAPI接口实现开始的。只是不同的SAPI接口实现会完成他们特定的工作,例如Apache的mod_php SAPI实现需要初始化从Apache获取的一些信息,在输出内容是将内容返回给Apache,其他的SAPI实现也类似。

单进程SAPI生命周期

CLI/CGI模式的PHP属于单进程的SAPI模式。这类的请求在处理一次请求后就关闭。也就是只会经过如下几个环节: 开始 - 请求开始 - 请求关闭 - 结束 SAPI接口实现就完成了其生命周期。

php执行的生命周期是怎样的?

单进程SAPI生命周期

启动

在调用每个模块的模块初始化前,会有一个初始化的过程,它包括:

  • 初始化若干全局变量

  • 初始化若干常量

  • 初始化Zend引擎和核心组件

  • 解析php.ini

  • 全局操作函数的初始化

  • 初始化静态构建的模块和共享模块(MINIT)

  • 禁用函数和类

ACTIVATION

在处理了文件相关的内容,PHP会调用php_request_startup做请求初始化操作。请求初始化操作,除了图中显示的调用每个模块的请求初始化函数外,还做了较多的其它工作,其主要内容如下:

  • 激活Zend引擎

  • 激活SAPI

  • 环境初始化

  • 模块请求初始化

运行

php_execute_script函数包含了运行PHP脚本的全部过程。

当一个PHP文件需要解析执行时,它可能会需要执行三个文件,其中包括一个前置执行文件、当前需要执行的主文件和一个后置执行文件。非当前的两个文件可以在php.ini文件通过auto_prepend_file参数和auto_append_file参数设置。如果将这两个参数设置为空,则禁用对应的执行文件。

对于需要解析执行的文件,通过zend_compile_file(compile_file函数)做词法分析、语法分析和中间代码生成操作,返回此文件的所有中间代码。如果解析的文件有生成有效的中间代码,则调用zend_execute(execute函数)执行中间代码。如果在执行过程中出现异常并且用户有定义对这些异常的处理,则调用这些异常处理函数。在所有的操作都处理完后,PHP通过EG(return_value_ptr_ptr)返回结果。

DEACTIVATION

PHP关闭请求的过程是一个若干个关闭操作的集合,这个集合存在于php_request_shutdown函数中。这个集合包括如下内容:

  1. 调用所有通过register_shutdown_function()注册的函数。

  2. 执行所有可用的__destruct函数。这里的析构函数包括在对象池(EG(objects_store)中的所有对象的析构函数以及EG(symbol_table)中各个元素的析构方法。

  3. 将所有的输出刷出去。

  4. 发送HTTP应答头。

  5. 遍历每个模块的关闭请求方法,执行模块的请求关闭操作。

  6. 销毁全局变量表(PG(http_globals))的变量。

  7. 通过zend_deactivate函数,关闭词法分析器、语法分析器和中间代码执行器。

  8. 调用每个扩展的post-RSHUTDOWN函数。只是基本每个扩展的post_deactivate_func函数指针都是NULL。

  9. 关闭SAPI,通过sapi_deactivate销毁SG(sapi_headers)、SG(request_info)等的内容。

  10. 关闭流的包装器、关闭流的过滤器。

  11. 关闭内存管理。

  12. 重新设置最大执行时间

结束

最终到了要收尾的地方了。

  • flush

sapi_flush将最后的内容刷新出去。其调用的是sapi_module.flush,在CLI模式下等价于fflush函数。

  • 关闭Zend引擎

zend_shutdown将关闭Zend引擎。

亚博登录不上我们应该是执行每个模块的关闭模块操作。在这里只有一个zend_hash_graceful_reverse_destroy函数将module_registry销毁了。当然,它最终也是调用了关闭模块的方法的,其根源在于在初始化module_registry时就设置了这个hash表析构时调用ZEND_MODULE_DTOR宏。而ZEND_MODULE_DTOR宏对应的是module_destructor函数。在此函数中会调用模块的module_shutdown_func方法,即PHP_RSHUTDOWN_FUNCTION宏产生的那个函数。

在关闭所有的模块后,PHP继续销毁全局函数表,销毁全局类表、销售全局变量表等。通过zend_shutdown_extensions遍历zend_extensions所有元素,调用每个扩展的shutdown函数。

多进程SAPI生命周期

通常PHP是编译为apache的一个模块来处理PHP请求。Apache一般会采用多进程模式, Apache启动后会fork出多个子进程,每个进程的内存空间独立,每个子进程都会经过开始和结束环节,不过每个进程的开始阶段只在进程fork出来以来后进行,在整个进程的生命周期内可能会处理多个请求。只有在Apache关闭或者进程被结束之后才会进行关闭阶段,在这两个阶段之间会随着每个请求重复请求开始-请求关闭的环节。如图2.2所示:

php执行的生命周期是怎样的?

多进程SAPI生命周期

多线程的SAPI生命周期

多线程模式和多进程中的某个进程类似,不同的是在整个进程的生命周期内会并行的重复着 请求开始-请求关闭的环节

php执行的生命周期是怎样的?

多线程SAPI生命周期