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 相关文章推荐
用PHP获取Google AJAX Search API 数据的代码
Mar 12 PHP
php下关于中英数字混排的字符串分割问题
Apr 06 PHP
PHP数组对比函数,存在交集则返回真,否则返回假
Feb 03 PHP
php中用数组的方法设置cookies
Apr 21 PHP
PHP内核介绍及扩展开发指南―基础知识
Sep 11 PHP
smarty自定义函数htmlcheckboxes用法实例
Jan 22 PHP
php获取远程文件大小
Oct 20 PHP
使用Codeigniter重写insert的方法(推荐)
Mar 23 PHP
php使用PDO下exec()函数查询执行后受影响行数的方法
Mar 28 PHP
PHP开发之用微信远程遥控服务器
Jan 25 PHP
thinkPHP5框架闭包函数与子查询传参用法示例
Aug 02 PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 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
与空气斗智斗勇的经典《Overlord》,传说中的“无稽之谈”
2020/04/09 日漫
php之readdir函数用法实例
2014/11/13 PHP
PHP实现搜索相似图片
2015/09/22 PHP
php-fpm.conf配置文件中文说明详解及重要参数说明
2018/10/10 PHP
基于jquery的二级联动菜单实现代码
2011/04/25 Javascript
jQuery简单tab切换效果实现方法
2015/04/08 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
基于Vue.js的表格分页组件
2016/05/22 Javascript
微信小程序模板和模块化用法实例分析
2017/11/28 Javascript
js实现转动骰子模型
2019/10/24 Javascript
JS时间戳与日期格式互相转换的简单方法示例
2021/01/30 Javascript
Vue实现简单购物车功能
2020/12/13 Vue.js
[01:04:01]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第一场
2014/05/24 DOTA
[01:58]DOTA2上海特级锦标赛现场采访:RTZ这个ID到底好不好
2016/03/25 DOTA
python基于BeautifulSoup实现抓取网页指定内容的方法
2015/07/09 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
pyenv虚拟环境管理python多版本和软件库的方法
2019/12/26 Python
Python MOCK SERVER moco模拟接口测试过程解析
2020/04/13 Python
浅谈django不使用restframework自定义接口与使用的区别
2020/07/15 Python
Django中和时区相关的安全问题详解
2020/10/12 Python
H5 canvas实现贪吃蛇小游戏
2017/07/28 HTML / CSS
微信html5页面调用第三方位置导航的示例
2018/03/14 HTML / CSS
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
美国中西部家用医疗设备商店:Med Mart(轮椅、踏板车、升降机等)
2019/04/26 全球购物
Melissa鞋英国官方网站:Nonnon
2019/05/01 全球购物
会计与审计毕业生自荐信范文
2013/12/30 职场文书
秋季运动会稿件
2014/01/30 职场文书
《月迹》教学反思
2014/02/19 职场文书
初三班主任寄语大全
2014/04/04 职场文书
公司授权委托书范文
2014/08/02 职场文书
承诺书范本
2015/01/21 职场文书
介绍信怎么写
2015/01/30 职场文书
幼儿园推普周活动总结
2015/05/07 职场文书
2016年度先进班组事迹材料
2016/03/01 职场文书
2019年暑期安全广播稿!
2019/07/03 职场文书
纯CSS实现酷炫的霓虹灯效果
2021/04/13 HTML / CSS