Zval 是 PHP 中最重要的数据结构之一(另一个比较重要的数据结构是 hash table),它包含了 PHP 中的变量值和类型的相关信息。
1,它是一个 struct,基本结构为
struct _zval_struct {
// 存储变量的值
zvalue_value value;
// 表示引用计数
zend_uint refcount__gc;
// 变量具体的类型
zend_uchar type;
// 表示是否为引用
zend_uchar is_ref__gc;
};
typedef struct _zval_struct zval;
2,Zval 在内核中的工作
$a = ['string' => 'life', 'object' => new stdClass()];
xdebug_debug_zval('a');
// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass());
/**
* zval.value = array('string' => 'life', 'object' => new stdClass());
* zval.is_ref__gc = 0;
* zval.type = 'array';
* zval.refcount__gc = 1;
*/
创建数组时,会创建一个 zval(与普通变量生成的 zval 非常类似,但也有很大不同,数组和对象这类复合型的变量在生成 zval 时,会为每个 key 项生成一个 zval 容器)
$c = &$a['string'];
xdebug_debug_zval('a');
// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass());
xdebug_debug_zval('c');
// c:(refcount = 2, is_ref = 1) = 'life';
数组引用给另一个变量时,会增加 zval 中 refcount 和 is_ref 值
$b = $a['object'];
xdebug_debug_zval('a');
// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
xdebug_debug_zval('b');
// b:(refcount = 2, is_ref = 0) = new stdClass();
数组赋值给另一个变量时,会增加 zval 中 refcount 值
$d = $b;
xdebug_debug_zval('b');
// b:(refcount = 3, is_ref = 0) = new stdClass();
xdebug_debug_zval('d');
// d:(refcount = 3, is_ref = 0) = new stdClass();
$c = 'new lift';
xdebug_debug_zval('a');
// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
xdebug_debug_zval('c');
// c:(refcount = 2, is_ref = 1) = 'new lift';
以上 c 引用 a['string'] 的值属于使用共享 zval 的形式,当 c 改变时 refcount 和 is_ref 值不变唯有 a 和 c 的 value 值改变
unset($c);
xdebug_debug_zval('a');
// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
unset 时,对应减少 zval 中 refcount 和 is_ref 值
php+Zval
最新推荐文章于 2021-03-24 13:24:23 发布