设为首页 收藏本站
查看: 592|回复: 0

[经验分享] 理解php原理的opcodes(操作码)

[复制链接]

尚未签到

发表于 2015-8-24 15:34:43 | 显示全部楼层 |阅读模式
  今天读了风雪之隅的一篇文章(深入理解PHP原理之Opcodes),发现自己对php的原理基本上都不了解,特别是深层的~呵呵,继续努力~

  把这篇博文自己的理解记录下来,加深理解~

  Opcondes是一种php脚本编译后的中间语言,就像Java的Byte Code,或者.NET 的MSL 。(都没了解过~)

  举个文中的例子  

  <?php   
     echo "Hello World";   
     $a = 1 + 1;   
     echo $a;
  ?>  PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)
  
  1.Scanning(Lexing) (扫描),将PHP代码转换为语言片段(Tokens)
  2.Parsing(语法分析), 将Tokens转换成简单而有意义的表达式
  3.Compilation(编译), 将表达式编译成Opocdes
  4.Execution(执行编译后的结果), 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
  
  其中他还提到一句:&#8220;现在有的Cache比如APC,可以使得PHP缓存住Opcodes,这样,每次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度。 &#8221; 这可能是php执行速度比较快的原因之一吧~  
  那什么是Lexing? 学过编译原理的同学都应该对编译原理中的词法分析步骤有所了解,Lex就是一个词法分析的依据表。 Zend/zend_language_scanner.c会根据Zend/zend_language_scanner.l(Lex文件),来输入的 PHP代码进行词法分析,从而得到一个一个的&#8220;词&#8221;,PHP4.2开始提供了一个函数叫token_get_all,这个函数就可以讲一段PHP代码 Scanning成Tokens;
   如果用这个函数处理我们开头提到的PHP代码,将会得到如下结果:

  • Array
  • (
  •     [0] => Array
  •         (
  •            [0] => 367
  •            [1] =>  Array
  •         (
  •             [0] => 316
  •             [1] => echo
  •         )
  •     [2] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [3] => Array
  •         (
  •             [0] => 315
  •             [1] => "Hello World"
  •         )
  •     [4] => ;
  •     [5] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [6] => =
  •     [7] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [8] => Array
  •         (
  •             [0] => 305
  •             [1] => 1
  •         )
  •     [9] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [10] => +
  •     [11] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [12] => Array
  •         (
  •             [0] => 305
  •             [1] => 1
  •         )
  •     [13] => ;
  •     [14] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [15] => Array
  •         (
  •             [0] => 316
  •             [1] => echo
  •         )
  •     [16] => Array
  •         (
  •             [0] => 370
  •             [1] =>
  •         )
  •     [17] => ;
  • )
  分析这个返回结果我们可以发现,源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。而,其他的比如标签,操作符, 语句,都会被转换成一个包含俩部分的Array: Token ID (也就是在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING),和源码中的原来的内容。
   接下来,就是Parsing阶段了,Parsing首先会丢弃Tokens Array中的多于的空格,然后将剩余的Tokens转换成一个一个的简单的表达式

  • 1.echo a constant string
  • 2.add two numbers together
  • 3.store the result of the prior expression to a variable
  • 4.echo a variable
  然后就改Compilation阶段了,它会把Tokens编译成一个个op_array, 每个op_arrayd包含如下5个部分:

  • 1.Opcode数字的标识,指明了每个op_array的操作类型,比如add , echo
  • 2.结果       存放Opcode结果
  • 3.操作数1  给Opcode的操作数
  • 4.操作数2
  • 5.扩展值   1个整形用来区别被重载的操作符
  比如,我们的PHP代码会被Parsing成:

  • * ZEND_ECHO     'Hello World'
  • * ZEND_ADD       ~0 1 1
  • * ZEND_ASSIGN  !0 ~0
  • * ZEND_ECHO     !0
  呵呵,你可能会问了,我们的$a去那里了?
  恩,这个要介绍操作数了,每个操作数都是由以下俩个部分组成:

  • a)op_type : 为IS_CONST, IS_TMP_VAR, IS_VAR, IS_UNUSED, or IS_CV
  • b)u,一个联合体,根据op_type的不同,分别用不同的类型保存了这个操作数的值(const)或者左值(var)
  而对于var来说,每个var也不一样
  IS_TMP_VAR, 顾名思义,这个是一个临时变量,保存一些op_array的结果,以便接下来的op_array使用,这种的操作数的u保存着一个指向变量表的一个句柄(整数),这种操作数一般用~开头,比如~0,表示变量表的0号未知的临时变量
  IS_VAR 这种就是我们一般意义上的变量了,他们以$开头表示
  IS_CV 表示ZE2.1/PHP5.1以后的编译器使用的一种cache机制,这种变量保存着被它引用的变量的地址,当一个变量第一次被引用的时候,就会被CV起来,以后对这个变量的引用就不需要再次去查找active符号表了,CV变量以!开头表示。
       这么看来,我们的$a被优化成!0了。
  
  本文原地址: http://www.laruence.com/2008/06/18/221.html

  
  总结:

  1.php的执行顺序是:  -> php程序

  -> 被Scanning(扫描转换为Tokens(语言片段))
  -> 被Parsing(语法分析,将Tokens转换成简单而有意义的表达式)
  -> Compilation(编译,将表达式编译成Opocdes(操作码))     
  -> Execution(顺序执行编译后的结果)
  
  2. APC(Alternative PHP Cache)的缓存机制可以缓存住Opcodes,这样,下次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度。  这可能是php执行速度比较快的原因之一

  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-103627-1-1.html 上篇帖子: PHP 201307 月最新手册chm 免费下载 下篇帖子: PHP Cookbook读书笔记 – 第16章互联网服务
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表