1.php是解析型的高级语言,zend内核使用c语言实现,有main函数,php脚本就是输入,内核处理后输出结果,内核将php脚本翻译成c程序可识别的opcode就是php的编译。
c语言的编译将c代码编译成机器码,这些机器码就是操作指令,将指令写入二进制程序load相应的内存区(常量区 数据区 代码区),分配运行栈,开始从代码区依次执行。
php编译差不多,将php脚本解析成opcode,每条opcode就是c的stuct,对应着相应的机器指令,执行过程就是zend引擎执行这些opcode,编译过程包括词法分析、语法分析,就的php版本直接生成opcode,php7新增在语法分析阶段生成抽象语法树,然后生成opcode_array。
2.词法分析、语法分析 (PHP代码->抽象语法树(AST))
PHP使用re2c、bison完成这个阶段的工作
re2c: 词法分析器,将输入分割为一个个有意义的词块,称为token
bison: 语法分析器,确定词法分析器分割出的token是如何彼此关联的
3.opcode_array结构
zend引擎会把AST进一步编译为 zend_op_array ,它是编译阶段最终的产物,也是执行阶段的输入。 AST解析过程确定了当前脚本定义了哪些变量,并为这些变量 顺序编号 ,这些值在使用时都是按照这个编号获取的,另外也将变量的初始化值、调用的函数/类/常量名称等值(称之为字面量)保存到zend_op_array.literals中,这些字面量也有一个唯一的编号,所以执行的过程实际就是根据各指令调用不同的C函数,然后根据变量、字面量、临时变量的编号对这些值进行处理加工。
PHP主脚本会生成一个zend_op_array,每个function也会编译为独立的zend_op_array,所以从二进制程序的角度看zend_op_array包含着当前作用域下的所有堆栈信息,函数调用实际就是不同zend_op_array间的切换
opcode的结构
struct _zend_op_array { //common是