摘要:對于來說,變量有全局變量和局部變量之分那么,他們都是存儲到一個哈希表內了么其實不是的,變量存儲也有作用域的概念。
上次跟大家講了垃圾回收機制后,有些小伙伴對底層原理比較感興趣,私信問我了一些關于變量的相關知識,既然大家對變量比較感興趣,那么這次我們來系統的講一下變量的底層原理
變量結構首先,我們還是先擺上我們的zval結構體,即php所有變量都會以zval結構體的形式實現
struct _zval_struct { union { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } value; //變量value值 zend_uint refcount__gc; //引用計數內存中使用次數,為0刪除該變量 zend_uchar type; //變量類型 zend_uchar is_ref__gc; //區分是否是引用變量,是引用為1,否則為0 };
從上面結構體內容可以看出每一個php變量都會由變量類型、value值、引用計數次數和是否是引用變量四部分組成
注:上面zval結構體是php5.3版本之后,php7版本之前的結構
變量類型看到這里,可能會有小伙伴們問我,php不是有8種數據類型嗎?但是為什么對應的zvalue的value值只有5種?
原因是這樣的,php出于對內存節省的考慮,所以對于一些變量類型做了復用,并沒有一一對應去定義每個變量類型
下面我們看一下zvalue的每個value值所對應的變量類型
zval.value.lval => 整型、布爾型、資源 zval.value.dval => 浮點型 zval.value.str => 字符串 zval.value.*ht => 數組 zval.value.obj => 對象
看到這里大家可能會比較奇怪,布爾型和資源是怎么對應到zval.value的lval上的呢?還有,NULL呢?
布爾型就像我們會將true和false映射成0和1進行數據庫存儲一樣,php也是這么做的。所以php發現zval的type值是布爾型時,會將布爾型轉成0或1存儲在zval.value的lval中
資源資源對于php來說屬于一個比較特殊的變量,而php會將每個資源對應的資源標識存儲在zval.value的lval中。常見的資源有:文件句柄、數據庫句柄等
NULL對于NULL來說,就更好理解了,因為本身通過zval的type值即可區分,所以并沒有將NULL值存儲在zval的value中
變量生成php作為一門動態語言,沒有先聲明變量后賦值的習慣,所以都是拿來一個變量直接就進行了賦值,那么是如何實現的呢?
舉例:
$name = "許錚的技術成長之路";變量容器生成
其實每次變量被常量賦值時,都會對應生成一個變量容器。剛才的例子會生成一個變量容器,容器的type是字符串類型,而value值則是許錚的技術成長之路,且此時該變量容器的ref_count會加1
變量名和變量容器關聯而變量name是如何與變量容器關聯起來的呢?其實也是使用了php的一個內部機制,即哈希表。每個變量的變量名和指向zval結構的指針被存儲在哈希表內,以此實現了變量名到變量容器的映射
變量作用域上面我們提到了變量名和變量容器映射的概念。對于php來說,變量有全局變量和局部變量之分;那么,他們都是存儲到一個哈希表內了么?
其實不是的,變量存儲也有作用域的概念。全局變量被存儲到了全局符號表內,而局部變量也就是指函數或對象內的變量,則被存儲到了活動符號表內(每個函數或對象都多帶帶維護了自己的活動符號表。活動符號表的生命周期,從函數或對象被調用時開始,到調用完成時結束)
變量銷毀變量銷毀,分為以下幾種情況:
1、手動銷毀
2、垃圾回收機制銷毀(引用計數清0銷毀和根緩沖區滿后銷毀)
我們這次主要講一下手動銷毀,即unset,每次銷毀時都會將符號表內的變量名和對應的zval結構進行銷毀,并將對應的內存歸還到php所維護的內存池內(按內存大小劃分到對應內存列表中)
而對于垃圾回收機制的銷毀,如果你不了解其相關原理,那么我建議你看下我之前寫的文章php底層原理之垃圾回收機制
思考今天,我們從底層的角度,將變量從生成到銷毀講了一遍。對于變量的生成,我們是拿常量賦值作為示例講解的,那么變量之間的賦值呢?是什么原理呢?且聽下回分解~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31041.html
摘要:但是對于結構體中的和字段我們一直都沒有詳細介紹過,而這兩個字段其實是和變量之間賦值的原理有著密切的關系的。 上周我們從底層的角度介紹了php變量從生成->常量賦值->銷毀的完整生命周期(不了解的同學可以翻看一下前面的文章php底層原理之變量(一)),但是我們留了一個思考,不知道大家有答案了沒,變量之間的賦值在底層又是如何實現的呢? 變量之間賦值 php變量的zval結構,我們已經介紹了...
摘要:數組是最常用的數據類型,同時容易上手也得益于其強大的數組,但是數組在中是如何實現的呢首先,我們還是先了解下相關的數據結構,為下面的內容打好基礎哈希表哈希表,顧名思義,即將不同的關鍵字映射到不同單元的一種數據結構。 數組是PHPer最常用的數據類型,同時php容易上手也得益于其強大的數組,但是數組在php中是如何實現的呢? 首先,我們還是先了解下相關的數據結構,為下面的內容打好基礎 哈希...
摘要:總結垃圾回收機制以的引用計數機制為基礎以前只有該機制同時使用根緩沖區機制,當發現有存在循環引用的時,就會把其投入到根緩沖區,當根緩沖區達到配置文件中的指定數量后,就會進行垃圾回收,以此解決循環引用導致的內存泄漏問題開始引入該機制 php垃圾回收機制,對于PHPer來說是一個不陌生但是又不是很熟悉的內容。那么php是怎么實現對不需要的內存進行回收的呢? php變量的內部存儲結構 首先還是...
摘要:所以想要理解更深入的同學最好查看下我之前的關于介紹變量函數的文章類的數據結構不管是普通類還是抽象類或是接口,都存放到統一的結構體中,并且在生成中間代碼時,會將此類添加到全局類列表中。 對于PHPer來說,OOP是不可或缺的開發思維,但是你對php類和對象的底層實現又了解多少呢?本著知其然且知其所以然的思想,讓我們一起來尋找答案~ 類的底層實現可看作是之前我們講過的變量、函數等的知識集合...
摘要:發現挺有意思的一個問題,內存溢出導致腳本執行失敗。那就一起來看個究竟吧首先查看了計劃任務的從報錯信息字面意思可以看出,允許的的內存已經用盡,還要試圖分配內存。給你當前腳本分配的內存你已經用完了,你還想問系統要內存。 今天上午剛到公司,就有同事在公司群里反映某個計劃任務出現問題了。我就懷著刨根問底的心,去查看了log。發現挺有意思的一個問題,PHP內存溢出導致腳本執行失敗。那就一起來看個...
閱讀 712·2021-10-14 09:42
閱讀 1966·2021-09-22 15:04
閱讀 1571·2019-08-30 12:44
閱讀 2133·2019-08-29 13:29
閱讀 2729·2019-08-29 12:51
閱讀 542·2019-08-26 18:18
閱讀 697·2019-08-26 13:43
閱讀 2803·2019-08-26 13:38