PHP源码分析之变量的存储过程分解


Posted in PHP onJuly 03, 2014

PHP代码如下:

$php_var = 1; 

对应C的代码是:

zval* c_var;    //定义PHP变量指针  

MAKE_STD_ZVAL(c_var);  //初始化PHP变量  

ZVAL_LONG(c_var,1) ;//赋值  

ZEND_SET_SYMBL( EG(active_symbol_table), " php_var ", c_var);//注册到全局变量符号表

一.首先看第一行: zval* c_var;//申明一个zval指针c_var; zval的结构如下:

struct _zval_struct {  

    /* Variable information */  

    zvalue_value value;     /* 变量的值 */  

    zend_uint refcount;     /* 引用计数,垃圾回收的时候用到 */  

    zend_uchar type;        /* 变量类型 */  

    zend_uchar is_ref;      /* 是否为引用变量 */  

};  

typedef struct _zval_struct zval; 

其中值zvalue_value的结构如下:

typedef union _zvalue_value {  

    long lval;              /* 长整形*/  

    double dval;            /* 双精度类型 */  

    struct {                  /* 字符串类型的值 */  

        char *val;              

        int len;  

    } str;  

    HashTable *ht;              /* 数组类型的值 */  

    zend_object_value obj;     /*对象类型的值*/  

} zvalue_value; 

二.接下来看第二行: MAKE_STD_ZVAL(new_val);//变量初始化 相关宏如下: //初始化

#define MAKE_STD_ZVAL(zv)                \  

    ALLOC_ZVAL(zv); \  

    INIT_PZVAL(zv);  

  

#define ALLOC_ZVAL(z)   \  

    ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)  

  

#define ZEND_FAST_ALLOC(p, type, fc_type)   \  

    (p) = (type *) emalloc(sizeof(type))  

  

#define INIT_PZVAL(z)       \  

    (z)->refcount = 1;      \  

    (z)->is_ref = 0; 

展开后为:

(c_var) = (zval *) emalloc(sizeof(zval));  //分配内存  

(c_var)-> refcount = 1;  //引用计数初始化  

(c_var)-> is_ref = 0; //是否引用 

可以看到其作用就是分配内存,初始化refcount,is_ref

三.下面看第三行 ZVAL_LONG(c_var,1) 相关宏为:

//定义值  

#define ZVAL_LONG(z, l) {           \  

     Z_TYPE_P(z) = IS_LONG;      \  

     Z_LVAL_P(z) = l;            \  

}  

#define Z_TYPE_P(zval_p)    Z_TYPE(*zval_p)  

#define Z_TYPE(zval)        (zval).type  

#define Z_LVAL_P(zval_p)    Z_LVAL(*zval_p)  

#define Z_LVAL(zval)            (zval).value.lval 

展开后为:

(* c_var).type = IS_LONG;  

(* c_var).value = 1; 

四:接下来看第四行: ZEND_SET_SYMBOL( EG(active_symbol_table), “php_var”, c_var); 首先说明下PHP的变量是存在一个hashtable里的

struct _zend_executor_globals {    

        ….  

        HashTable symbol_table;//全局变量的符号表    

        HashTable *active_symbol_table;//局部变量的符号表    

        …..  

    };   

Hashtable的Key为变量的名称,即php_var,值为指向PHP变量的指针,即c_var指针; 相关宏为:

#define ZEND_SET_SYMBOL(symtable, name, var)          \   {                                                     \  

        char *_name = (name);                         \  

        ZEND_SET_SYMBOL_WITH_LENGTH(symtable, _name, strlen(_name)+1, var, 1, 0);   \  

}  

//主要的实现为下面这个函数:  

#define ZEND_SET_SYMBOL_WITH_LENGTH(symtable, name, name_length, var, _refcount, _is_ref)                                                       \  

    {                                                                         

        zval **orig_var;                                        \   

        if (zend_hash_find(symtable, (name), (name_length), (void **) &orig_var)==SUCCESS                                                         \  

            && PZVAL_IS_REF(*orig_var)) {                     \  

            (var)->refcount = (*orig_var)->refcount;                  \  

            (var)->is_ref = 1;                                \  

            if (_refcount) {                                      \  

                (var)->refcount += _refcount-1;               \  

            }                                             \  

            zval_dtor(*orig_var);                             \  

            **orig_var = *(var);                                  \  

            FREE_ZVAL(var);                               \  

        } else {                                              \  

            (var)->is_ref = _is_ref;                              \  

            if (_refcount) {                                      \  

                (var)->refcount = _refcount;                      \  

            }                                             \  

            zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL);                                                           \  

        }                                                  \  

    }            

该函数的功能是:
1. 如果全局符号表已经存在该变量且是引用类型,则

a. 将原来变量的引用计数refcount,is_ref信息赋给c_var;
b. 释放掉原来变量zvalue的值,比如原来其值指向的是一个mysql连接资源,则释放该资源。
c. 将c_var指向的变量赋值给原来的变量 d. 释放c_var的内存空间 这样保证了,如果变量被应用,值一起改变。比如如果前面有$b=&a;

2. 如果全局符号表不存在该变量或者存在该变量但不是引用变量,则直接改变其值。

PHP 相关文章推荐
WIN98下Apache1.3.14+PHP4.0.4的安装
Oct 09 PHP
关于UEditor编辑器远程图片上传失败的解决办法
Aug 31 PHP
PHP fastcgi模式上传大文件(大约有300多K)报错
Sep 28 PHP
php实现上传图片文件代码
Jul 19 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
Yii2 assets清除缓存的方法
May 16 PHP
PHP如何实现跨域
May 30 PHP
Yii2简单实现给表单添加验证码的方法
Jul 18 PHP
Laravel学习教程之model validation的使用示例
Oct 23 PHP
PHP+redis实现的悲观锁机制示例
Jun 12 PHP
laravel model模型处理之修改查询或修改字段时的类型格式案例
Oct 17 PHP
tp5框架基于ajax实现异步删除图片的方法示例
Feb 10 PHP
ThinkPHP让分页保持搜索状态的方法
Jul 02 #PHP
ThinkPHP实现批量删除数据的代码实例
Jul 02 #PHP
Thinkphp中import的几个用法详细介绍
Jul 02 #PHP
改写ThinkPHP的U方法使其路由下分页正常
Jul 02 #PHP
PHP反射使用实例和PHP反射API的中文说明
Jul 02 #PHP
用PHP解决的一个栈的面试题
Jul 02 #PHP
函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐
Jul 02 #PHP
You might like
example1.php
2006/10/09 PHP
php生成4位数字验证码的实现代码
2015/11/23 PHP
分享五个PHP7性能优化提升技巧
2015/12/07 PHP
PHP正则获取页面所有图片地址
2016/03/23 PHP
PHP实现的折半查询算法示例
2017/10/09 PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
2018/08/21 PHP
laravel实现前后台路由分离的方法
2019/10/13 PHP
PHP7新增函数
2021/03/09 PHP
Javascript中的相等与不等运算
2010/04/25 Javascript
JS正则验证邮箱的格式详细介绍
2013/11/19 Javascript
js加入收藏夹代码(兼容ie/ff/op)
2014/05/16 Javascript
JS实现快速的导航下拉菜单动画效果附源码下载
2016/11/01 Javascript
jQuery中的siblings()是什么意思(推荐)
2016/12/29 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
基于Vue框架vux组件库实现上拉刷新功能
2017/11/28 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
微信小程序使用for循环动态渲染页面操作示例
2018/12/25 Javascript
js 判断当前时间是否处于某个一个时间段内
2019/09/19 Javascript
小程序外卖订单界面的示例代码
2019/12/30 Javascript
ES2020系列之空值合并运算符 '??'
2020/07/22 Javascript
详细分析JavaScript中的深浅拷贝
2020/09/17 Javascript
[15:56]Heroes18_暗影萨满(完美)
2014/10/31 DOTA
Python的装饰器使用详解
2017/06/26 Python
python基础知识(一)变量与简单数据类型详解
2019/04/17 Python
Django Admin中增加导出Excel功能过程解析
2019/09/04 Python
python实现将json多行数据传入到mysql中使用
2019/12/31 Python
tensorflow 分类损失函数使用小记
2020/02/18 Python
利用python绘制正态分布曲线
2021/01/04 Python
浏览器实现移动端高性能css3动画(开启gpu加速)
2013/12/23 HTML / CSS
课改先进个人汇报材料
2014/01/26 职场文书
驾驶员安全责任书范本
2014/07/24 职场文书
乡镇平安建设汇报材料
2014/08/25 职场文书
优秀党员先进材料
2014/12/18 职场文书
2015年服务员工作总结
2015/04/08 职场文书
2015年施工员工作总结范文
2015/04/20 职场文书
幼儿园师德师风心得体会
2016/01/12 职场文书