PHP世界的原子-zval探秘

要想研究一个世界,要从宏观和微观两个角度来看。研究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]也发生了变化了吧?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • PHP执行原理** php是一门应用非常简单,开发效率极高的一门语言,其弱类型的变量能省去程序员大量的定义变量、类...
    人在码途阅读 1,460评论 1 7
  • 我或许,总是迷茫于人生的归宿,却忽略人生的本质其实是过程。没有绝对到不了的地方,差别只在于你选择的路远还是近,曲折...
    此去经年_df96阅读 153评论 0 0
  • 二零一七年八月二十四日 姓名:李义 公司:慈溪创鑫车辆零部件有限公司 组别:259期利他二组 【知~学习】 背诵 ...
    六度轮回阅读 114评论 0 0