【PHP7内核剖析】——PHP的编译与执行

我们都知道,PHP是一门编译型语言,那除了编译型语言,计算机还有什么语言呢?一般来说,计算机语言分为两类,一种就是C/C++等的编译型语言,另外一种是PHP的解释型语言。那解释型语言与编译型语言有什么区别呢?那个又更好呢?我们先来扒一扒这两种语言的解释吧!

编译型语言:程序在运行之前先将语言编译成计算机可执行的二级制文件,在执行时直接执行机器指令。

解释型语言:程序在运行时有解释器边编译边执行,又称脚本语言。

这两种语言用例子来说的话,我们可以把编译型语言当作是饭先做好了再吃,而解释型语言就好比说火锅,边涮边吃!

编译型语言不是咱们的重点,咱们不多说,说说PHP这种解释型语言吧。前面说过,解释型语言是用解释器边编译边执行的,那么,PHP的解释器是什么呢?ZendVM。就和Java中的JVM一样,ZendVM就是PHP语言的解释器,这也是整合PHP内核中最为核心的地方。一个PHP程序运行的过程为:

从上面我们可以看到,PHP语言与计算机之间多了一层解释器,这个解释器完美的解决了跨平台的问题,使得PHP这种解释型语言可以任意跨平台开发,但是,这也导致了解释型语言的效率远远不如编译型语言。而且,同样的计算,解释型语言往往比编译型语言需要执行更多的指令来完成!由此来看,这两种语言也没有谁更好的说法,只能说是你的项目更适合使用什么语言了。

接下来我们继续探究PHP的层面。上面说到了ZendVM是PHP中内核中最为核心的部分,那我们就来深入的研究一下ZendVM这个虚拟机。ZendVM有两部分组成:编译器与执行器。其中编译器负责将PHP代码解释成ZendVM可识别的指令(opline),执行器负责执行opline中的opcode对应的机器指令。

先看一下opline的结构:

struct _zend_op {
	const void *handler;
	znode_op op1;
	znode_op op2;
	znode_op result;
	uint32_t extended_value;
	uint32_t lineno;
	zend_uchar opcode;
	zend_uchar op1_type;
	zend_uchar op2_type;
	zend_uchar result_type;
};

整个opline的结构我们可以分成两部分来看,前面是opline的操作数,后面是处理动作。

其中op1,op2,result分别指的是操作数1,操作数2,返回值。opcode为指令编码,唯一标识一个指令动作。目前PHP总共定义了173条opcode,我们常用的赋值,循环,判断等都在这173条opcode中。handle为每条opcode对应的实际处理函数。

通过上面的学习,我们已经知道了opline是一条指令,那么多条指令呢?PHP中定义了一个zend_op_array结构保存多个编译生成的数据。

接下来我们来看一下PHP的编译。配合拍的编译过程就是将PHP脚本代码转成opcode指令的过程。具体为:

其中,在词法分析,语法分析阶段,分别使用re2c词法扫描器与yacc语法分析器。抽象语法树的编译就是生成ZendVM可识别的指令。语法分析之后,ZendVM会把抽象语法树进一步编译成zend_op_array。

再我们来看一下PHP的执行。ZendVM执行器有指令处理headler与调度器组合而成。执行时,有执行器调用相应的handler完成指令的处理;调度器负责控制指令的执行,以及执行器上下文的切换,有调度器发起handler的执行。

总结:目前本人对这快的理解深度还不够,后面需要重新找时间在深入源码研读一下原理。如果正好你也感兴趣的话,欢迎随时骚扰,咱们一起探讨,一起学习!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章