msgbartop
PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
msgbarbottom

12 Aug 08 深入理解PHP原理之函数(Introspecting PHP Function)

在PHP中,函数分为俩种,

  • 一种是zend_internal_function, 这种函数是由扩展或者Zend/PHP内核提供的,用’C/C++’编写的,可以直接执行的函数。
  • 另外一种是zend_user_function, 这种函数呢,就是我们经常在见的,用户在PHP脚本中定义的函数,这种函数最终会被ZE翻译成opcode array来执行
  • 查看zend_compile.h,我们可以找到如下的3个结构:

    typedef struct _zend_internal_function {
        /* Common elements */
        zend_uchar type;
        char * function_name;
        zend_class_entry *scope;
        zend_uint fn_flags;
        union _zend_function *prototype;
        zend_uint num_args;
        zend_uint required_num_args;
        zend_arg_info *arg_info;
        zend_bool pass_rest_by_reference;
        unsigned char return_reference;
        /* END of common elements */
    
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
        struct _zend_module_entry *module;
    } zend_internal_function;
    
    struct _zend_op_array {
        /* Common elements */
        zend_uchar type;
        char *function_name;
        zend_class_entry *scope;
        zend_uint fn_flags;
        union _zend_function *prototype;
        zend_uint num_args;
        zend_uint required_num_args;
        zend_arg_info *arg_info;
        zend_bool pass_rest_by_reference;
        unsigned char return_reference;
        /* END of common elements */
    
        zend_uint *refcount;
    
        zend_op *opcodes;
        zend_uint last, size;
    
        zend_compiled_variable *vars;
        int last_var, size_var;
    
        zend_uint T;
    
        zend_brk_cont_element *brk_cont_array;
        zend_uint last_brk_cont;
        zend_uint current_brk_cont;
    
        zend_try_catch_element *try_catch_array;
        int last_try_catch;
    
        /* static variables support */
        HashTable *static_variables;
    
        zend_op *start_op;
        int backpatch_count;
    
        zend_bool done_pass_two;
        zend_bool uses_this;
    
        char *filename;
    
         zend_uint line_start;
        zend_uint line_end;
        char *doc_comment;
        zend_uint doc_comment_len;
    
        void *reserved[ZEND_MAX_RESERVED_RESOURCES];
    };
    
    typedef union _zend_function {
        zend_uchar type;    /* MUST be the first element of this struct! */
    
        struct {
            zend_uchar type;  /* never used */
            char *function_name;
            zend_class_entry *scope;
            zend_uint fn_flags;
            union _zend_function *prototype;
            zend_uint num_args;
            zend_uint required_num_args;
            zend_arg_info *arg_info;
            zend_bool pass_rest_by_reference;
            unsigned char return_reference;
        } common;
    
        zend_op_array op_array;
        zend_internal_function internal_function;
    } zend_function;
        

    第一个结构,定义了zend_internal_function, 当PHP启动的时候 ,它会遍历每个载入的扩展模块,然后将模块中function_entry中指明的每一个函数, 创建一个zend_internal_function结构, 并将type置为ZEND_INTERNAL_FUNCTION(见下表), 将这个结构填入全局的函数表(一个HashTable);

    #define ZEND_INTERNAL_FUNCTION              1
    #define ZEND_USER_FUNCTION                  2
    #define ZEND_OVERLOADED_FUNCTION            3
    #define ZEND_EVAL_CODE                      4
    #define ZEND_OVERLOADED_FUNCTION_TEMPORARY  5
          

    第二个结构,op_array, 这个结构很重要, 因为:

          extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
       

    也就是说,我们编写的PHP脚本,都会被ZE翻译成op_array, 最后交由zend_execute执行。

    另外,在ZE中,用户定义的函数(userland function), 也会被翻译成一个op_array, 并填入全局函数表中。这个时候scope,function_name都不为空。而对于在全局作用域的直接代码来说,最后的op_array的scope为全局,function_name为空。

    第三个结构, 很有趣, 要理解这个结构,首先你要理解他的设计目标: zend_internal_function, zend_function,zend_op_array可以安全的互相转换(The are not identical structs, but all the elements that are in “common” they hold in common, thus the can safely be casted to each other);

    具体来说,当在op code中通过ZEND_DO_FCALL调用一个函数的时候,ZE会在函数表中,根据名字(其实是lowercase的函数名字,这也就是为什么PHP的函数名是大小写不敏感的)查找函数, 如果找到,返回一个zend_function结构的指针(仔细看这个上面的zend_function结构), 然后判断type,如果是ZEND_INTERNAL_FUNCTION, 那么ZE就调用zend_execute_internal,通过zend_internal_function.handler来执行这个函数, 如果不是,就调用zend_execute来执行这个函数包含的zend_op_array.


    分享到:



    Related Posts:

    Tags: , ,

    18 Responses to “深入理解PHP原理之函数(Introspecting PHP Function)”

    1. Mcrypt响应慢的一个原因[转] | 屎壳君的博客 |

      [...] PHP的函数(Introspecting PHP Function) [...]

    2. xiaoq |

      鸟哥在给php内核代码的时候应该把版本号给add上。比如对于
      struct _zend_op_array
      PHP 5.4.10版本的结构体定义中并没有看到
      zend_bool pass_rest_by_reference;
      unsigned char return_reference;
      这两个字段。

    3. pangee |

      typedef union _zend_function {
      zend_uchar type; /* MUST be the first element of this struct! */

      ? why the type must be the first element of _zend_function???

    4. php 底层 探究之 函数(Introspecting PHP Function) | Buddy Laboratory |

      [...] 转载自:http://www.laruence.com/2008/08/12/164.html 返回 [...]

    5. php 底层 探究之 函数(Introspecting PHP Function) | Buddy Laboratory |

      [...] 转载自:http://www.laruence.com/2008/08/12/164.html 返回 [...]

    6. 如何调试PHP的Core(一) | 风雪之隅 |

      [...] 这些知识在我之前的文章中都有过涉及, 大家可以翻阅: 深入理解PHP原理之函数 [...]

    7. PHP Reflection Extension的一个bug | 风雪之隅 |

      [...] 而我们都知道, PHP的function_table中的函数都是小写的(参看我之前的文章深入理解PHP原理之函数(Introspecting PHP Function)). 于是reflection extension的如下这段代码就会报错: if (module->functions && [...]

    8. 深入理解PHP原理之函数(Introspecting PHP Function) | 万维网黑客联盟 |

      [...] 本文地址: http://www.laruence.com/2008/08/12/164.html [...]

    9. sexy nightwear |

      这个函数表的结构和普通的函数表一样(深入理解 PHP之函数), 也是以zend_op_array为最终载体, 所以和普通函数一样

    10. ClarkeJUANA35 |

      If you are willing to buy a house, you would have to receive the loans. Furthermore, my brother always takes a term loan, which is really firm.

    11. 深入理解 PHP之require/include顺序 « 大熊猫 – konakona ——PHP程序员 |

      [...] 这个函数表的结构和普通的函数表一样(深入理解 PHP之函数), 也是以zend_op_array为最终载体, 所以和普通函数一样, [...]

    12. 深入理解PHP原理之对象(一) « phplife |

      [...] 这个函数表的结构和普通的函数表一样(深入理解PHP之函数), 也是以zend_op_array为最终载体, 所以和普通函数一样, [...]

    13. 深入理解PHP原理之对象(一) | 风雪之隅 |

      [...] 这个函数表的结构和普通的函数表一样(深入理解PHP之函数), 也是以zend_op_array为最终载体, 所以和普通函数一样, [...]

    14. IntingeMeatty |

      Love Epicentre is one of the most popular online dating sites, and has a huge member database with thousands of free profiles to browse. It is a trusted and safe online dating site that caters to long term relationship seekers and finds your match based on personality traits.

    15. Ande Lang |

      em… chinese?

    16. yongtao.pang |

      学习了,期待下一篇

    17. 雪候鸟 |

      ….., 相关度为0的留言

    18. sue |

      留言:Brett Anderson很帅

    Leave a Reply

    *