变量改变时PHP内核做了些什么?

| 时间:2015-09-19 02:48:20 | 阅读数:

[导读] 内容来自于《Extending and Embedding PHP》- Chaper 3 - Memory Management,加上自己的理解,对php中变量的引用计数、写时复制,写时改变,写时复制和改变做个”翻译

引言

内容来自于《Extending and Embedding PHP》- Chaper 3 - Memory Management,加上自己的理解,对php中变量的引用计数、写时复制,写时改变,写时复制和改变做个”翻译“。

zval

看下面的内容之前先对zval这个结构体做个了解

typedef struct _zval_struct {
    zvalue_value value;
    zend_uint refcount;
    zend_uchar type;
    zend_uchar is_ref;
} zval;

zval结构体中共有4个元素,value是一个联合体,用来真正的存储zval的值,refcount用来计数该zval被多少个变量使用,type表示zval所存储的数据类型,is_ref用来标志该zval是否被引用。

引用计数那样,$a$b指向相同的zval,修改$b之后$a不是也变了?
这个具体是怎么实现的呢,我们一起来看下:

  • $a = 1;内核创建一个zval,并分配4个字节存储数字1。
  • $b = $a;这一步和中的第二步一样,将$b指向和$a相同的zval,并将zval中的引用计数值refcount加1。
  • $b += 5;关键是这一步,这一步骤发生了什么呢,怎么确保修改之后不影响$a

    • 其实Zend内核在改变zval之前都会去进行get_var_and_separete操作,如果recfount>1,就需要分离就创建新的zval返回,否则直接返回变量所指向的zval,下面看看如何分离产生新的zval。
    • 复制一个和$b所指向zval一样的zval。
    • $b所指向的zval中的refcount计数减1。
    • 初始化生成的新zval,设置refcount=1,is_ref=0。
    • $b指向新生成的zval。
    • 对新生成的zval进行操作,这就是写时复制。
      下面看看内核中分离时的主要代码:中的第一步一样。

    • $b = &$a;这一步骤内核会将$b指向$a所指向的zval,将zval中的refcount加1,并将zval中的is_ref置为1。
    • $b += 5;这一步骤和中的第三步骤一样,但是内核中发生的事情却不一样。

      • 内核看到$b进行变化的时候,也会执行函数,看是否需要分离。
      • 如果(*varval)->is_ref的话也会直接返回$b所指向的zval,不去分离产生新的zval,不管zval的refcount是否>1。
      • 这时候再去修改$b值,$a的值也就改变了,因为他们指向相同的zval。

    分离的问题

    说道现在聪明的你可能已经看出点问题了,如果一个zval结构体既有refcount计数又有is_ref引用这个时候怎么办?

    <?php
        $a = 1;
        $b = $a;
        $c = &$a;
    ?>

    如果出现上面这种情况的时候,如果$a、$b、$c指向同一个zval结构体,进行改变的时候Zend到底去听谁的?其实这个地方不会指向同一个zval了。
    如果对一个is_ref = 0 && refcount >1的zval进行写时改变这种赋值形式(就是引用赋值)的时候,Zend会将等号右边的变量分离出来一个新的zval,
    对这个zval进行初始化,对之前的zval的refcount进行减1操作,让等号左边的变量指向这个新的zval,refcount进行加1操作,is_ref=1。看看下面这张图片

    <?php
        $a = 1;
        $b = &$a;
        $c = $a;
    ?>

    上面这又是另外一种情况,在is_ref = 1的情况下,试图单纯的进行refcount+1操作的时候会分离出来一个新的zval给等号左边的变量,并初始化他,看看下面这张图片

    参考文献

    1.《Extending and Embedding PHP》- Chaper 3 - Memory Management.

手机扫描下方二维码,关注php100官方微信。

同步官网每日更新,为您带来随时随地的资讯与技术信息。
更有不定期的互动抽奖活动,赢取实用贴心的小礼物。

除非特别声明,PHP100新闻均为原创或投稿报道,转载请注明作者及原文链接
原文地址:

延伸阅读 More

粤ICP备15117877号-3