PHP如何执行程序

PHP的执行与别的程序运行不一样,至少在web服务器模式下不一样,别的语言是以进程为单位,有常驻内存的变量、对象,而PHP是以请求为单位,每次请求时实例化一次程序初始化各种变量。简单来说就是PHP内核会对PHP代码进行词法分析、语法分析,把代码转为Zend Engine可执行的操作,然后Zend Engine对这些操作执行顺序的执行。整个过程中Zend Engine是PHP内核的核心部分,负责最终操作的执行和结果的返回。

在PHP进程的开始阶段会执行模块初始化(MINIT),此过程只进行一次,主要为了完成注册扩展模块,执行模块初始化。在每次发生请求前都会执行模块激活(RINIT)。一个请求结束后就执行停用模块(RSHUTDOWN),而整个PHP结束时调用关闭模块(MSHUTDOWN)。

SAPI(Server Application Programming Interface)是PHP的应用编程接口,Apache、Nginx、IIS、CLI分别通过各自的SAPI接口与PHP通信,传入参数执行脚本并得到结果。在各个服务器抽象层之间遵守的相同约定称之为SAPI接口。目前PHP中存在的SAPI接口实现有:aolserver,apache,apache2filter,apache2handler,cgi,cli,phttpd,tux,webjgames等。SAPI的接口是由名为_sapi_module_struct指定的。

所谓SAPI声明周期,其实就是PHP进程的生命周期。SAPI生命周期分为:单进程SAPI生命周期、多进程SAPI生命周期以及多线程SAPI声明周期。它们之间的过程都是类似的。

CLI/CGI模式的PHP就是单进程SAPI模式,此类请求在处理一次请求之后就关闭。如图: 单进程SAPI模式 跟上面描述的阶段是一样的,此处再补充一些内容。 在调用MINIT之前会启动操作,包括初始化全局变量、常量,初始化Zend引擎和核心组件,解析php.ini文件,注册内置模块和共享模块,在此之后才是遍历每个模块,调用每个模块的模块初始化函数。 在请求达到和调用RINIT之间的阶段叫ACTIVATION,期间会初始化编译器,初始化符号表(symbol_table)和对象池(objects_store),初始化执行虚拟栈、符号表。另外还会针对HTTP请求设置$_GET、$_POST、$_COOKIE、$_SERVER、$_ENV、$_FILES等变量。在此之后将遍历所有注册的模块的RINIT方法。 当执行PHP文件时,可能会执行三个文件:前置执行文件、主文件、后置执行文件。前置和后置文件用php.ini中auto_prepend_file和auto_append_file参数设置。执行阶段将对编译PHP文件,生成中间代码,并调用zend_execute执行中间代码。在所有操作处理完后返回结果。 PHP关闭请求称为DEACTIVATION,销毁对象池和符号表,将所有输出刷新出去,发送HTTP应答头,调用所有注册模块的RSHUTDOWN方法,销毁HTTP变量,关闭内存管理等执行与ACTIVATION相反的操作。 当进程退出时,将所有模块关闭,并调用其MSHUTDOWN方法。

Apache采用多进程SAPI模式,整个生命周期内可能有多个请求开始-请求关闭的循环。 多进程SAPI模式 最后的是多线程SAPI模式: 多线程API模式