一直以来,横观国内的PHP现状,很少有专门介绍PHP内部机制的书。呵呵,我会随时记录下研究的心得,有机会的时候,汇总成书。:)
今天这篇,我内心是想打算做为一个导论:
PHP是一个被广泛应用的脚本语言,因为它的成功,所以很多时候,我们应用PHP的时候是更不不需要考虑底层到底是怎么实现的。我相信大多数的 PHP程序 员是不会去考虑这一点的。从我接触PHP开始,到今天也就是3年,这三年里,前俩年我一直都是在”用”PHP,每次写出来一段脚本,我就会想“恩,不用担 心,PHP解释器会知道我想做什么的”,直到去年来到雅虎,接受了一个工作,是做一个PHP的Extension,从这个时候开始,我就好奇于新接触的一 大堆的新鲜事物,zend, TSRM, zval, hashtable, op_array…
于是我到处查阅资料,每次获得一篇好的文章,或者一段好的文字我就会如获珍宝,打印保存起来,细细研读。我发现,国内关于PHP内部的资料真是少的 可怜, 不知道是因为懂得的人多但是不愿意分享,还是懂得的人本来就少,所以,这条路,我走的很辛苦。于是,就会有了这篇文章。
在这篇文章中,我会从整个PHP的执行期入手,大致的介绍下各个阶段,词法分析,语法分析,op code等等,以后的文章我会再详细介绍每个阶(当然,如果你急不可耐的想知道详细,呵呵,那么可以直接联系我)。
从最初我们编写的PHP脚本->到最后脚本被执行->得到执行结果,这个过程,其实可以分为如下几个阶段(鄙视:CSDN不能上图):
首先,Zend Engine(ZE),调用词法分析器(Lex生成的,源文件在 Zend/zend_language_sanner.l), 将我们要执行的PHP源文件,去掉空格 ,注释,分割成一个一个的token。
然后,ZE会将得到的token forward给语法分析器(yacc生成, 源文件在 Zend/zend_language_parser.y),生成一个一个的op code,opcode一般会以op array的形式存在,它是PHP执行的中间语言。
最后,ZE调用zend_executor来执行op array,输出结果。
ZE是一个虚拟机,正是由于它的存在,所以才能使得我们写PHP脚本,完全不需要考虑所在的操作系统类型是什么。ZE是一个CISC(复杂指令处理器), 它支持150条指令(具体指令在 Zend/zend_vm_opcodes.h),包括从最简单的ZEND_ECHO(echo)到复杂的 ZEND_INCLUDE_OR_EVAL(include,require),所有我们编写的PHP都会最终被处理为这150条指令(op code)的序列,从而最终被执行。
那有什么办法可以看到我们的PHP脚本,最终被“翻译”成什么样的呢? 也就是说,op code张的什么样子呢? 呵呵,达到这个,我们需要重新编译PHP,修改它的compile_file和zend_execute函数。不过,在PECL中已经有这样的模块,可以 让我们直接使用了,那就是由 Derick Rethans开发的VLD (Vulcan Logic Dissassembler)模块。你只要下载这个模块,并把他载入PHP中,就可以通过简单的设置,来得到脚本翻译的结果了。具体关于这个模块的使用说 明-雅虎一下,你就知道^_^。
接下来,让我们尝试用VLD来查看一段简单的PHP脚本的中间语言。
原始代码:
<?php $i = “This is a string“; //I am comments echo $i.‘ that has been echoed to screen‘; ?>
采用VLD得到的op codes:
filename:/home/Desktop/vldOutOne.php function name: (null) number of ops: 7 line # op fetch ext operands ——————————————————————————————————————————-
2 0 FETCH_W local $0, ‘i‘ 1 ASSIGN $0, ‘This+is+a+string‘ 4 2 FETCH_R local $2, ‘i‘ 3 CONCAT ~3, $2,‘+that+has+been+echoed+to+screen‘ 4 ECHO ~3 6 5 RETURN 1 6 ZEND_HANDLE_EXCEPTION
我们可以看到,源文件中的注释,在op code中,已经没有了,所以不用担心注释太多会影响你的脚本执行时间(实际上,它是会影响ZE的词法处理阶段的用时而已)。
现在我们来一条一条的分析这段op codes,每一条op code 又叫做一条op_line,都由如下7个部分,在zend_compile.h中,我们可以看到如下定义:
struct _zend_op { opcode_handler_t handler; znode result; znode op1; znode op2; ulong extended_value; uint lineno; zend_uchar opcode; };
其中,opcode字段指明了这操作类型,handler指明了处理器,然后有俩个操作数,和一个操作结果。
- FETCH_W, 是以写的方式获取一个变量,此处是获取变量名”i”的变量于$0(*zval)。
- 将字符串”this+is+a+string”赋值(ASSIGN)给$0
- 字符串连接
- 显示
可以看出,这个很类似于很多同学大学学习编译原理时候的三元式,不同的是,这些中间代码会被Zend VM(Zend虚拟机)直接执行。
真正负责执行的函数是,zend_execute, 查看zend_execute.h:
可以看出, zend_execute接受zend_op_array*作为参数。
可以看到,zend_op_array的结构和zend_function的结构很像(参看我的其他文章), 对于在全局作用域的代码,就是不包含在任何function内的op_array,它的function_name为NULL。结构中的opcodes保 存了属于这个op_array的op code数组,zend_execute会从start_op开始,逐条解释执行传入的每条op code, 从而实现我们PHP脚本想要的结果。
下一次,我将介绍PHP变量的灵魂 – zval, 你将会看到PHP是如何实现它的变量传递,类型戏法,等等。
分享到:
相关推荐
Exploring Blazor
Exploring Curvature 一本细致讲解曲率的书
Exploring ES6
Exploring complex networks
Exploring Java introduces the basics of Java, the hot new object-oriented programming language for networked applications from Sun Microsystems. Exploring Java enables programmers to quickly get up to...
ESRI ArcGIS AO开发书籍Exploring ArcObjects
Exploring_Expect.pdf, by Li Ke Yang
Exploring C++ 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
Exploring ArcObjects
Exploring Oracle Internals
Exploring Chemistry with Electronic Structure Methos, Second Edition, 作者James B. Foresman, Eleen Frisch 出版社Gaussian, Inc, USA, 1996 前言 Gaussian可以做很多事情,具体包括 分子能量和结构研究 过渡态...
Exploring Chemistry With Electronic Structure Methods 第二版
Exploring C++ 中文版,C++进阶书籍。PDF扫描版,比较清晰。
Exploring ArcObjects 9.0 part 2
这本书比阮一峰老师那本《ES6入门》更深入,翻译质量也挺好的,值得一读。 翻译版权归译者。 Exploring JS: JavaScript books for programmers Most of the following books are free to read online. I hope you...
此书为加书签版! expect教程书,关注expect的书就两本,一体expect,一本exploring expect,此书是第一版,也是绝版,此PDF为完整版,无缺页
Exploring Arcobjects中文版第1章
Exploring .NET Core with Microservices Exploring .NET Core with Microservices
Exploring ES2016 and ES2017