返回首页
当前位置: 主页 > 编程语言 > PHP教程 >

PHP源码 — 变量

时间:2015-05-26 23:34来源:电脑教程学习网 www.etwiki.cn 编辑:admin

变量是一切系统和语言的基础。

变量是简单的。

当然哲学告诉我们事物必然要从简单发展到复杂、再次发展到简单。

PHP 中定义变量非常的简单只用了一个包含4个成员的变量 _zval_struct
struct _zval_struct {
zvalue_value value;/* value */
zend_uint refcount__gc;
zend_uchar type;/* active type */
zend_uchar is_ref__gc;
};

先说说这四个成员变量的作用

/*存放变量的值*/
zvalue_value value;
/*变量引用计数*/
zend_uint refcount__gc;
/* 变量类型*/
zend_uchar type;
/*是否强制引用标记*/
zend_uchar is_ref__gc;

zvalue_value value; 数据结构
typedef union _zvalue_value {
long lval;/* long value */
double dval;/* double value */
struct {
char *val;
int len;
} str;
HashTable *ht;/* hash table value */
zend_object_value obj;
zend_ast *ast;
} zvalue_value;

变量的定义,并且赋值。
<?php
$a=”hello a”;
?>

源码实现:
/*
定义部分
*/
Zval *z_a;
MAKE_STD_ZVAL(z_a);
/*
变量赋值
*/
ZVAL_STRING(z_a, "hello a", 0);

/*
保存到全局变量表中,这个时候才有变量名字叫$a
*/
ZEND_SET_SYMBOL(EG(active_symbol_table), "a", z_a);

MASK_STD_ZVAL 函数宏定义
#define MAKE_STD_ZVAL(zv) \
ALLOC_ZVAL(zv); \
INIT_PZVAL(zv);

其实是申请一块内存
(p) = (type *) emalloc(sizeof(type))

申请完内存,进行cow的前置操作
#define INIT_PZVAL(z) \
(z)->refcount__gc = 1; \
(z)->is_ref__gc = 0;

引用计数初始化为1,强制引用初始化为0

可以通过xdebug 来检测
<?php
xdebug_debug_zval('a');
?>

情况如下:
(refcount=1, is_ref=0),string ’1′ (length=1)

前面我们以ZVAL_STRING 字符串定义为例子
#define ZVAL_STRING(z, s, duplicate) { \
const char *__s=(s); \
Z_STRLEN_P(z) = strlen(__s); \
Z_STRVAL_P(z) = (duplicate?estrndup(__s, Z_STRLEN_P(z)):(char*)__s);\
Z_TYPE_P(z) = IS_STRING; \
}

所以我建议在使用 ZVAL_STRING(z_a, “hello a”, 0);
estrndup 函数原型
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;

p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
return p;
}
memcpy(p, s, length);
p[length] = 0;
return p;
}

可以看出是通过 _emalloc 去申请 length +1 的内存长度。

变量查找

PHP的内核数据结构严格意义上说其实只有一种就是hashTable。所以变量的检查/检索就是hashtable的检索。
ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData)

这几方法我们来拆分下

zend_hash_find(那个hashTable,查找的名字,名字的程度,zval* 这个数据结构去存放);

例子:
zval **z_a;

if (zend_hash_find(EG(active_symbol_table),
"a", sizeof("a"),
(void**)&z_a) == SUCCESS)
{
php_printf("$a");
}
else
{
php_printf("$a is not defined.");
}

变量内存使用

PHP 的变量是存放在symbol_table中。

我们通过memory_get_usage 看下内存使用情况
<?php
var_dump(memory_get_usage(TRUE));
$a = "hello a";
var_dump(memory_get_usage(TRUE));
?>

int 262144
int 262144
都是 262144,难道没有用到内存?

当然这是因为PHP 在启动的时候会向系统申请一定的内存,后面变量的一切内存操作都是PHP向系统申请的这块内存区域进行操作。

再看个例子:
<?php
var_dump(memory_get_usage());
$a = "hello a";

------分隔线----------------------------
标签(Tag):php php实例教程 php5 php源代码 php基础教程 php技巧 php6 php教程
------分隔线----------------------------
推荐内容
猜你感兴趣