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 相关文章推荐
织梦模板标记简介
Mar 11 PHP
PHP file_get_contents 函数超时的几种解决方法
Jul 30 PHP
php 广告调用类代码(支持Flash调用)
Aug 11 PHP
php class中self,parent,this的区别以及实例介绍
Apr 24 PHP
解析PHP中数组元素升序、降序以及重新排序的函数
Jun 20 PHP
PHP基于CURL进行POST数据上传实例
Nov 10 PHP
CI框架给视图添加动态数据
Dec 01 PHP
php实现只保留mysql中最新1000条记录
Jun 18 PHP
WordPress开发中用于标题显示的相关函数使用解析
Jan 07 PHP
PHP中key和current,next的联合运用实例分析
Mar 29 PHP
PHP数组生成XML格式数据的封装类实例
Nov 10 PHP
php mysql获取表字段名称和字段信息的三种方法
Nov 13 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
PHPMailer使用教程(PHPMailer发送邮件实例分析)
2012/12/06 PHP
smarty中js的调用方法示例
2014/10/27 PHP
PHP排序算法类实例
2015/06/17 PHP
PHP实用小技巧之调用录像的方法
2019/12/05 PHP
一段好玩的JavaScript代码
2006/12/01 Javascript
javascript实现轮显新闻标题链接
2007/08/13 Javascript
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
2008/12/25 Javascript
jquery form表单提交插件asp.net后台中文解码
2010/06/12 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
2015/09/26 Javascript
jQuery插件扩展测试实例
2016/06/21 Javascript
jQuery通用的全局遍历方法$.each()用法实例
2016/07/04 Javascript
功能强大的Bootstrap效果展示(二)
2016/08/03 Javascript
使用JQuery选择HTML遍历函数的方法
2016/09/17 Javascript
jQuery实现边框动态效果的实例代码
2016/09/23 Javascript
easyui-combobox 实现简单的自动补全功能示例
2016/11/08 Javascript
浅谈js在html中的加载执行顺序,多个jquery ready执行顺序
2016/11/26 Javascript
解决VUEX刷新的时候出现数据消失
2017/07/03 Javascript
Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法
2017/09/20 Javascript
微信小程序 POST请求的实例详解
2017/09/29 Javascript
jQuery中库的引用方法
2018/01/06 jQuery
vue源码中的检测方法的实现
2019/09/26 Javascript
JavaScript实现轮播图效果代码实例
2019/09/28 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
Android基于TCP和URL协议的网络编程示例【附demo源码下载】
2018/01/23 Python
Python使用遗传算法解决最大流问题
2018/01/29 Python
Python打开文件,将list、numpy数组内容写入txt文件中的方法
2018/10/26 Python
python统计文章中单词出现次数实例
2020/02/27 Python
python实现简单猜单词游戏
2020/12/24 Python
CSS3属性box-shadow使用指南
2014/12/09 HTML / CSS
CSS3+Sprite实现僵尸行走动画特效源码
2016/01/27 HTML / CSS
CSS3实现红包抖动效果
2020/12/23 HTML / CSS
HTML5之WebGL 3D概述(上)—WebGL原生开发开启网页3D渲染新时代
2013/01/31 HTML / CSS
de Bijenkorf比利时官网:荷兰最知名的百货商店
2017/06/29 全球购物
介绍一下Linux文件的记录形式
2013/09/29 面试题
道德大讲堂实施方案
2014/05/14 职场文书
工商局局长个人对照检查材料思想汇报
2014/09/23 职场文书