函数的存储结构

3.2.1.1 函数的存储结构

下面具体看下PHP中函数的结构:

typedef union  _zend_function        zend_function;

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

    struct {
        zend_uchar type;  /* never used */
        zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */
        uint32_t fn_flags;
        zend_string *function_name;
        zend_class_entry *scope; //成员方法所属类,面向对象实现中用到
        union _zend_function *prototype;
        uint32_t num_args; //参数数量
        uint32_t required_num_args; //必传参数数量
        zend_arg_info *arg_info; //参数信息
    } common;

    zend_op_array op_array; //函数实际编译为普通的zend_op_array
    zend_internal_function internal_function;
};

这是一个union,因为PHP中函数除了用户自定义函数还有一种:内部函数,内部函数是通过扩展或者内核提供的C函数,比如time、array系列等等,内部函数稍后再作分析。

内部函数主要用到internal_function,而用户自定义函数编译完就是一个普通的opcode数组,用的是op_array(注意:op_array、internal_function是嵌入的两个结构,而不是一个单独的指针),除了这两个上面还有一个typecommon,这俩是做什么用的呢?

经过比较发现zend_op_arrayzend_internal_function结构的起始位置都有common中的几个成员,如果你对C的内存比较了解应该会马上想到它们的用法,实际common可以看作是op_arrayinternal_function的header,不管是什么哪种函数都可以通过zend_function.common.xx快速访问到zend_function.zend_op_array.xxzend_function.zend_internal_function.xx,下面几个,type同理,可以直接通过zend_function.type取到zend_function.op_array.typezend_function.internal_function.type

php function

函数是在编译阶段确定的,那么它们存在哪呢?

在PHP脚本的生命周期中有一个非常重要的值executor_globals(非ZTS下),类型是struct _zend_executor_globals,它记录着PHP生命周期中所有的数据,如果你写过PHP扩展一定用到过EG这个宏,这个宏实际就是对executor_globals的操作:define EG(v) (executor_globals.v)

EG(function_table)是一个哈希表,记录的就是PHP中所有的函数。

PHP在编译阶段将用户自定义的函数编译为独立的opcodes,保存在EG(function_table)中,调用时重新分配新的zend_execute_data(相当于运行栈),然后执行函数的opcodes,调用完再还原到旧的zend_execute_data,继续执行,关于zend引擎execute阶段后面会详细分析。

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3