PHP底层工作原理

简介

  • php相关进程是随着Apache的启动而运行的;PHP通过mod_php5.so模块和Apache相连(具体说来是SAPI,即服务器应用程序编程接口)
  • PHP总共有三个模块:内核、Zend引擎、以及扩展层;PHP内核用来处理请求、文件流、错误处理等相关操作
  • Zend引擎(ZE)用以将源文件转换成机器语言,然后在虚拟机上运行它
  • 扩展层是一组函数、类库和流,PHP使用它们来执行一些特定的操作(比如,我们需要mysql扩展来连接MySQL数据库)
  • 当ZE执行程序时可能会需要连接若干扩展,这时ZE将控制权交给扩展,等处理完特定任务后再返还
  • 最后,ZE将程序运行结果返回给PHP内核,它再将结果传送给SAPI层,最终输出到浏览器上

流程

  1. PHP启动第一步—->[模块初始化(扩展)]
    启动Apache后,PHP解释程序也随之启动;
    PHP调用各个扩展的MINIT方法,从而使这些扩展切换到可用状态。看看php.ini文件里打开了哪些扩展吧;
    MINIT的意思是“模块初始化”。各个模块都定义了一组函数、类库等用以处理其他请求。
  2. PHP启动第二步—->[请求初始化(变量)]
    当一个页面请求发生时,SAPI层将控制权交给PHP层。于是PHP设置了用于回复本次请求所需的环境变量。
    同时,它还建立一个变量表,用来存放执行过程中产生的变量名和值
    PHP调用各个模块的RINIT方法,即“请求初始化”。

    1
    2
    3
    4
    5
    一个经典的例子是Session模块的RINIT,如果在php.ini中启用了Session模块,那在调用该模块的RINIT时就会初始化$_SESSION变量,并将相关内容读入;RINIT方法可以看作是一个准备过程,在程序执行之间就会自动启动。
    一个典型的RINIT方法如下:
    PHP_RINIT_FUNCTION(extension_name) {
    /* Initialize session variables, pre-populate variables, redefine global variables etc */
    }
  3. PHP关闭第一步—>[变量销毁]
    一旦页面执行完毕(无论是执行到了文件末尾还是用exit或die函数中止),PHP就会启动清理程序。
    它会按顺序调用各个模块的RSHUTDOWN方法。RSHUTDOWN用以清除程序运行时产生的符号表,也就是对每个变量调用unset函数。

  4. PHP关闭第二步—>[扩展释放]
    PHP调用每个扩展的MSHUTDOWN方法,这是各个模块最后一次释放内存的机会

Zend引擎

Zend整体用纯c实现,是php的内核部分,它将php代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕zend实现。

Extensions

围绕着zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的php中间层、富文本解析就是extension的典型应用)。

Sapi

Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,sapi通过一系列钩子函数,使得php可以和外围交互数据,这是php非常优雅和成功的一个设计,通过sapi成功的将php本身和上层应用解耦隔离,php可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式

1
2
3
4
5
6
7
8
9
Unix/Linux环境下:
LoadModule php5_module modules/mod_php5.so
AddType application/x-httpd-php .php
注:其中modules/mod_php5.so 是X系统环境下mod_php5.so文件的安装位置。
Windows环境下:
LoadModule php5_module d:/php/php5apache2.dll
AddType application/x-httpd-php .php
注:其中d:/php/php5apache2.dll 是在Windows环境下php5apache2.dll文件的安装位置。
这两项配置就是告诉Apache Server,以后收到的Url用户请求,凡是以php作为后缀,就需要调用php5_module模块(mod_php5.so/ php5apache2.dll)进行处理。

上层应用

这就是我们平时编写的php程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。

谢谢您请我喝咖啡!