PHP世界的原子-zval探秘

要想研究一個(gè)世界,要從宏觀和微觀兩個(gè)角度來(lái)看。研究php也是一樣的。直接寫(xiě)php代碼算是從宏觀角度去研究了php,而從微觀角度開(kāi)始研究php,自然就要從zval開(kāi)始了。

如果把php比作一個(gè)世界的話(huà),zval可以算是這個(gè)世界的原子了。它是php變量的實(shí)際存儲(chǔ)單元,貫通了整個(gè)php的世界。

zval是在Zend2中引入的,后來(lái)在php7中,zval的結(jié)構(gòu)做了擴(kuò)展。不過(guò)這次主要研究的是php5的zval,php7的有機(jī)會(huì)再研究。

首先拉下來(lái)一份php的源碼(https://github.com/php/php-src)。切到分支PHP-5.6.26,打開(kāi)Zend/zend_types.h,在55行能看到如下代碼:

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

可以看出,zval這個(gè)結(jié)構(gòu)體有4個(gè)部分,value保存了具體的值,而type則指明了這個(gè)具體值的類(lèi)型。refcount__gc和is_ref__gc從名字能看出跟gc有關(guān),但其實(shí)他們不僅僅是跟gc有關(guān),還有更重要的用途。

is_ref__gc說(shuō)明了這個(gè)zval是否被是引用的。而refcount__gc說(shuō)明了有幾個(gè)變量是這個(gè)值:比如有兩個(gè)變量都是一樣的值,那么在底層這兩個(gè)變量指向的都是同一個(gè)zval,然后refcount__gc會(huì)被設(shè)為2。如果有三個(gè)變量都指向這個(gè)值,那么refcount__gc就是3。如果其中一個(gè)變量發(fā)生變化的話(huà),才會(huì)建立新的zval,原來(lái)的zval的refcount__gc減1。這種機(jī)制就是寫(xiě)時(shí)復(fù)制,copy-on-write。

上面是zvalue_value的定義,這是個(gè)union。它可以被解讀為長(zhǎng)整數(shù),雙精度浮點(diǎn)數(shù),一個(gè)字符串指針和相應(yīng)的字符串長(zhǎng)度,hashtable指針,php對(duì)象或者是php常量的表達(dá)式抽象樹(shù)。具體采用哪種解讀,則是看zval結(jié)構(gòu)體的type字段。

接下來(lái)要隆重介紹一個(gè)壓箱底的函數(shù),它可以查看每個(gè)變量的zval:debug_zval_dump()。配合這個(gè)函數(shù),我們可以看看refcount__gc是怎么變化的。

這段代碼的結(jié)果如下:

我們來(lái)一個(gè)個(gè)分析。

首先是上面的$a、$b和$c,它們的refcount都是4,明明只有三個(gè)變量但為啥是4呢?其實(shí)除了它們3個(gè)自身之外,在函數(shù)調(diào)用傳值時(shí)也復(fù)制了一次變量,所以在3個(gè)之外還得加1,也就成了4。

而中間的三個(gè)怎么又變成了3、3、2呢?簡(jiǎn)單想想就能發(fā)現(xiàn),因?yàn)榘l(fā)生了寫(xiě)時(shí)復(fù)制,建立了新的zval給了$c,所以它的refcount成了1,傳入函數(shù)變成了2。而$a和$b指向的zval少了$c,自然refcount就會(huì)減1了。

至于最后三個(gè),$d成了$a的引用,需要改寫(xiě)zval的is_ref為1,于是發(fā)生了寫(xiě)時(shí)復(fù)制,所以$b的zval的refcount再次減1。而$a和$d都指向同一個(gè)zval,而且它們是引用就不再發(fā)生寫(xiě)時(shí)復(fù)制,自然refcount就保持在了1。

大概zval就介紹完了,其實(shí)很簡(jiǎn)單。但是有個(gè)思考題:

相信你這么聰明,應(yīng)該能想明白為啥改了$c[1],$a[1]也發(fā)生了變化了吧?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • PHP執(zhí)行原理** php是一門(mén)應(yīng)用非常簡(jiǎn)單,開(kāi)發(fā)效率極高的一門(mén)語(yǔ)言,其弱類(lèi)型的變量能省去程序員大量的定義變量、類(lèi)...
    人在碼途閱讀 1,536評(píng)論 1 7
  • 我或許,總是迷茫于人生的歸宿,卻忽略人生的本質(zhì)其實(shí)是過(guò)程。沒(méi)有絕對(duì)到不了的地方,差別只在于你選擇的路遠(yuǎn)還是近,曲折...
    此去經(jīng)年_df96閱讀 223評(píng)論 0 0
  • 二零一七年八月二十四日 姓名:李義 公司:慈溪?jiǎng)?chuàng)鑫車(chē)輛零部件有限公司 組別:259期利他二組 【知~學(xué)習(xí)】 背誦 ...
    六度輪回閱讀 128評(píng)論 0 0

友情鏈接更多精彩內(nèi)容