美文网首页技术文
PHP世界的原子-zval探秘

PHP世界的原子-zval探秘

作者: 齐思谬想 | 来源:发表于2016-09-22 08:29 被阅读0次

要想研究一个世界,要从宏观和微观两个角度来看。研究php也是一样的。直接写php代码算是从宏观角度去研究了php,而从微观角度开始研究php,自然就要从zval开始了。

如果把php比作一个世界的话,zval可以算是这个世界的原子了。它是php变量的实际存储单元,贯通了整个php的世界。

zval是在Zend2中引入的,后来在php7中,zval的结构做了扩展。不过这次主要研究的是php5的zval,php7的有机会再研究。

首先拉下来一份php的源码(https://github.com/php/php-src)。切到分支PHP-5.6.26,打开Zend/zend_types.h,在55行能看到如下代码:

而在Zend/zend.h的334行,能看到_zval_struct的定义。

可以看出,zval这个结构体有4个部分,value保存了具体的值,而type则指明了这个具体值的类型。refcount__gc和is_ref__gc从名字能看出跟gc有关,但其实他们不仅仅是跟gc有关,还有更重要的用途。

is_ref__gc说明了这个zval是否被是引用的。而refcount__gc说明了有几个变量是这个值:比如有两个变量都是一样的值,那么在底层这两个变量指向的都是同一个zval,然后refcount__gc会被设为2。如果有三个变量都指向这个值,那么refcount__gc就是3。如果其中一个变量发生变化的话,才会建立新的zval,原来的zval的refcount__gc减1。这种机制就是写时复制,copy-on-write。

上面是zvalue_value的定义,这是个union。它可以被解读为长整数,双精度浮点数,一个字符串指针和相应的字符串长度,hashtable指针,php对象或者是php常量的表达式抽象树。具体采用哪种解读,则是看zval结构体的type字段。

接下来要隆重介绍一个压箱底的函数,它可以查看每个变量的zval:debug_zval_dump()。配合这个函数,我们可以看看refcount__gc是怎么变化的。

这段代码的结果如下:

我们来一个个分析。

首先是上面的$a、$b和$c,它们的refcount都是4,明明只有三个变量但为啥是4呢?其实除了它们3个自身之外,在函数调用传值时也复制了一次变量,所以在3个之外还得加1,也就成了4。

而中间的三个怎么又变成了3、3、2呢?简单想想就能发现,因为发生了写时复制,建立了新的zval给了$c,所以它的refcount成了1,传入函数变成了2。而$a和$b指向的zval少了$c,自然refcount就会减1了。

至于最后三个,$d成了$a的引用,需要改写zval的is_ref为1,于是发生了写时复制,所以$b的zval的refcount再次减1。而$a和$d都指向同一个zval,而且它们是引用就不再发生写时复制,自然refcount就保持在了1。

大概zval就介绍完了,其实很简单。但是有个思考题:

相信你这么聪明,应该能想明白为啥改了$c[1],$a[1]也发生了变化了吧?

相关文章

  • PHP世界的原子-zval探秘

    要想研究一个世界,要从宏观和微观两个角度来看。研究php也是一样的。直接写php代码算是从宏观角度去研究了php,...

  • PHP7变量的内部实现

    PHP5中的zval PHP5中zval结构体的定义如下: 可以看到,zval由value、type和一些额外的_...

  • php7中的zval结构体

    php7中的zval结构体对比php5优化了很多,一个zval只占用16字节的空间,php7中的zval的结构体如...

  • php7 zval及变量存储方式

    Zval是PHP中最重要的数据结构之一,它包含了PHP中变量的值和类型相关信息。 1. zval 1.1 zval...

  • 引用

    php 引用变量 概念、定义、zval变量容器(用xdebug查看 xdebug_debug_zval('a'))...

  • PHP引用计数

    1. PHP官方手册引用计数介绍 引用计数每个php变量存在一个叫"zval"的变量容器中。一个zval变量容器,...

  • PHP5垃圾回收机制

    在了解垃圾回收机制之前我们必须先来看下zval结构。zval是用于保存变量以及常量的。 php5中的zval数据结...

  • php7的zval相关介绍

    在php7中变量主要由zval保存,只占用16个字节zval结构如下 zval主要由value u1 和u2保...

  • php5和php7-zval

    php5中的zval 1.php5zval中每个字段都明确定义不可修改,为解决循环引用只能进行扩充后实际占用32字...

  • PHP之zval的实现

    PHP5中zval中的实现 基于php-5.6.40 中php-5.6.40/Zend/zend.h PHP5的z...

网友评论

    本文标题:PHP世界的原子-zval探秘

    本文链接:https://www.haomeiwen.com/subject/antzettx.html