/ 学习

PHP底层运行机制和原理

0x01 开个头

本文的主要内容来自http://www.cnblogs.com/phpworld/p/5916560.html,转载加一点自己的体会。我最早接触php是在大一的寒假,当时对web开发没有任何感觉,就看视频,那个时候微信开发比较火,教程是用php+sae做微信开发,这也是我自己的一个转折点,与Web搭上交道。

0x02 PHP的设计理念及特点

  • 多进程模型,php是多进程模型,不同的请求调用间互不干涉,这样可以保证一个请求挂掉了不会对其他进程造成影响。
  • 弱类型语言,php是一门弱类型语言,这种机制使得其就像python那样方便开发
  • 引擎(Zend)+组件(Ext)的模式降低内部耦合。之前看phpinfo经常看到zend,现在才知道原来他是php的引擎。
  • 语法简单灵活,没有太多规范。缺点导致风格混杂,但再差的程序员也不会写出太离谱危害全局的程序。

0x03 PHP的框架体系

PHP的框架体系

PHP从下到上是一个四层体系:

  • Zend引擎:Zend引擎用纯C实现,是PHP的内核部分,它将PHP代码编译为可执行的opcode并实现相应的处理方法、实现了基本的数据结构、内存分配及管理、提供了相应的API方法供外部调用,是一切的核心。
  • Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的PHP中间层、富文本解析就是extension的典型应用)。
  • Sapi:Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
  • 上层应用:这就是我们平时编写的PHP程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。

0x04 PHP的执行流程&opcode

PHP实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用C实现的,因此最终调用的也都是C的函数,实际上,我们可以把PHP看做是一个C开发的软件。
PHP的执行的核心是翻译出来的一条一条指令,也即opcode。
Opcode是PHP程序执行的最基本单位。一个opcode由两个参数(op1,op2)、返回值和处理函数组成。PHP程序最终被翻译为一组opcode处理函数的顺序执行

0x05 PHP变量

PHP是一门弱类型语言,本身不严格区分变量的类型。PHP在变量申明的时候不需要指定类型。PHP在程序运行期间可能进行变量类型的隐示转换。和其他强类型语言一样,程序中也可以进行显示的类型转换。PHP变量可以分为简单类型(int、string、bool)、集合类型(array resource object)和常量(const)。以上所有的变量在底层都是同一种结构 zval。

struct _zval_struct {
    zvalue_value value;     /* value */
    zend_uint refcount__gc;  /* variable ref count */
    zend_uchar type;          /* active type */
    zend_uchar is_ref__gc;    /* if it is a ref variable */
};
typedef struct _zval_struct zval;
typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {                    /* string */
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value,used for array */
    zend_object_value obj;      /* object */
} zvalue_value;