成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

php7內(nèi)核閱讀(1)--數(shù)據(jù)容器zval和zend_value

canger / 3188人閱讀

摘要:本文主要是針對,的話可以移步到慶哥的博客看,還有就是小菜我讀的是內(nèi)核剖析這本書。接下來我會(huì)使用到來調(diào)試源碼本文有參照博客中的部分內(nèi)容以及代碼。

前言

工作+實(shí)習(xí)快一年了,搞php后端開發(fā),一直很迷茫怎么提高自己,就先從php源碼開始吧,本人比較菜,本文章寫的比較趕時(shí)間,所以有什么錯(cuò)誤或者漏掉的地方,望各位大神指正,多交流才能成長嘛,嘿嘿。
本文主要是針對php7,php5的話可以移步到慶哥的博客看,還有就是小菜我讀的是《php7內(nèi)核剖析》這本書。
接下來我會(huì)使用到xdebug來調(diào)試php源碼

本文有參照ohmygirl博客中的部分內(nèi)容以及代碼。

本文所用環(huán)境為windows,php7.0.10

php7中zval,zend_value的基本結(jié)構(gòu)

php7和php5不同的地方有很多,zval,zend_value結(jié)構(gòu)就是其中之一

在php7中

zval定義在zend_types.h中

在zval這個(gè)結(jié)構(gòu)體重包含三個(gè)部分 zend_value(存儲(chǔ)實(shí)際的內(nèi)容),u1,u2兩個(gè)聯(lián)合體,其中u1主要存儲(chǔ)變量相關(guān)的一下屬性,而u2則是對u1的一些補(bǔ)充,例如當(dāng)用到數(shù)組的時(shí)候,會(huì)用到u2.next來解決key哈希后出現(xiàn)的hash沖突

struct _zval_struct {
    zend_value        value;            /* 存儲(chǔ)變量的實(shí)際內(nèi)容 */
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    type,            /* 存儲(chǔ)變量的類型 */
                zend_uchar    type_flags,  /* 用于標(biāo)識(shí)變量狀態(tài),例如GC方面的管理,通過設(shè)置為IS_TYPE_COLLECTABLE 則變量會(huì)被收集到GC中回收垃圾的buffer緩存區(qū)中 */
                zend_uchar    const_flags,
                zend_uchar    reserved)        /* call info for EX(This) */
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t     next;                 /* hash collision chain */
        uint32_t     cache_slot;           /* literal cache slot */
        uint32_t     lineno;               /* line number (for ast nodes) */
        uint32_t     num_args;             /* arguments number for EX(This) */
        uint32_t     fe_pos;               /* foreach position */
        uint32_t     fe_iter_idx;          /* foreach iterator index */
        uint32_t     access_flags;         /* class constant access flags */
        uint32_t     property_guard;       /* single property guard */
        uint32_t     extra;                /* not further specified */
    } u2;  
};

zend_uchar type: 以下為外部使用的變量類型

#define IS_UNDEF                    0
#define IS_NULL                        1
#define IS_FALSE                    2
#define IS_TRUE                        3
#define IS_LONG                        4
#define IS_DOUBLE                    5
#define IS_STRING                    6
#define IS_ARRAY                    7
#define IS_OBJECT                    8
#define IS_RESOURCE                    9
#define IS_REFERENCE                10

php7中zend_value結(jié)構(gòu)

typedef union _zend_value {
    zend_long         lval;                /* long value */
    double            dval;                /* double value */
    zend_refcounted  *counted;          /*用于統(tǒng)計(jì)計(jì)數(shù)用,*/
    zend_string      *str;
    zend_array       *arr;
    zend_object      *obj;
    zend_resource    *res;
    zend_reference   *ref;
    zend_ast_ref     *ast;
    zval             *zv;
    void             *ptr;
    zend_class_entry *ce;
    zend_function    *func;
    struct {
        uint32_t w1;
        uint32_t w2;
    } ww;
} zend_value;

這里我們先解釋一下php7的zval,zend_valu中重要的的幾個(gè)變量

zval中:

(1)zend_uchar    type 這個(gè)是用來表示當(dāng)前變量(例如 $a)是什么類型的變量($a是string類型?還是int類型?還是引用類型....)

zend_value中:

(1)zend_refcounted  *counted; 表示引用計(jì)數(shù)的次數(shù),
何為引用計(jì)數(shù)?
就是zend_value變量被zval引用的次數(shù),例如我們$a=“abcs”;$c=$a;$b=$a;此時(shí)counted=3,如下圖,其中refcount也是實(shí)現(xiàn)GC自動(dòng)內(nèi)存回收的基礎(chǔ),下面會(huì)詳細(xì)講解

php7變量的內(nèi)部實(shí)現(xiàn)

php7中對與變量的實(shí)現(xiàn)分以下幾種方式


(1).對于boolen類型,還有null,undefined,這種沒有具體值,只有類型的類型,直接在zval中通過zend_uchar type的類型來判斷,無需通過引用計(jì)數(shù)來實(shí)現(xiàn)。

正是因?yàn)闆]有通過應(yīng)用計(jì)數(shù)來實(shí)現(xiàn),所以它refcount為0

(2)對于int類型和float類型,因?yàn)樵趜end_value中有zend_long和double來保存數(shù)據(jù),如下圖,所以,在賦值的時(shí)候就不需要再使用引用計(jì)數(shù)了,在拷貝的直接進(jìn)行賦值就行了,這樣做可以省掉大量引用計(jì)數(shù)的相關(guān)操作

定義一個(gè)$a=1,在php內(nèi)核中zval和zend_value的關(guān)系

(3)第三種就是常規(guī)的使用引用計(jì)數(shù)的方式來進(jìn)行來進(jìn)行變量的定義。在這些變量的實(shí)現(xiàn)中,都是通過指針指向一個(gè)具體的數(shù)據(jù)類型

例如 :
    zend_string  *str;
    struct _zend_string {
        zend_refcounted_h gc;
        zend_ulong        h;                /* hash value */
        size_t            len;
        char              val[1];
    };

$假設(shè)我定義一個(gè)$a="111";其內(nèi)部的實(shí)現(xiàn)就是,注意這里zend_string中char val[1],主要是因?yàn)镃語言中字符串是以“0”結(jié)尾的,所以在zend_string中$a="111"這個(gè)變量值的存儲(chǔ)是char val[4]="111"。



php7中賦值

1.普通賦值
前面說到,在php中,定義一個(gè)變量$a="444",實(shí)際上是生成了一個(gè)zval,和一個(gè)zend_value,然后zval指向這個(gè)zend_value來實(shí)現(xiàn)對$a="444"的定義的,然后通過refcount來統(tǒng)計(jì)引用的次數(shù)。

**所以可以總結(jié)出,refcount表示當(dāng)前有多少個(gè)zval指向同一個(gè)zend_value**

我們定義如下:

$a="111";
$b=$a;

當(dāng)然對于像boole型還有int,double,null變量,他們的直接通過zval保存,不會(huì)公用一個(gè)zend_value,所以直接使用深拷貝。
至于什么是深拷貝,什么是淺拷貝,最直接的區(qū)別就是在于有沒有重新生成一個(gè)一模一樣的zend_value,詳細(xì)請參看深拷貝和淺拷貝。
后面的寫時(shí)賦值(COW copy on write)就會(huì)使用到深拷貝。

對于php的賦值,實(shí)際上并不是所有的類型都是一樣的,剛剛也有說到,在php的zval中就有一個(gè)專門的字段用于標(biāo)識(shí)當(dāng)前類型適合哪種形式的那就是。

    zend_uchar    type_flags,

                | refcounted | collectable | copyable | immutable
----------------+------------+-------------+----------+----------
simple types    |            |             |          |
string          |      x     |             |     x    |
interned string |            |             |          |
array           |      x     |      x      |     x    |
immutable array |            |             |          |     x
object          |      x     |      x      |          |
resource        |      x     |             |          |
reference       |      x     |             |          |

zend_uchar type_flags這個(gè)字段用于標(biāo)識(shí)當(dāng)前的zval的屬于哪種賦值方式或者處于哪種狀態(tài),主要是用于內(nèi)存方面的管理具體參見內(nèi)存管理,

2.引用賦值

php中的引用賦值就是我們常用的引用,例如$a=&$b,這樣。

在php7中實(shí)現(xiàn)引用的時(shí)候,在php中實(shí)現(xiàn)引用的時(shí)候,會(huì)先生成一個(gè)zend_reference類型,這個(gè)類型中嵌套一個(gè)zval,然后這個(gè)zval的zend_value會(huì)指向之前的之前的那個(gè)zval的zend_value,原來的那個(gè)zval類型轉(zhuǎn)換成IS_REFERENCE類型,簡單來說**就是將原有的zval類型轉(zhuǎn)換成IS_REFERENCE,并新生成zend_reference類型指向原zend的zend_value。(好jb繞,理了好久)。

struct _zend_reference {
    zend_refcounted_h gc;
    zval              val;
};

例如我們定義一個(gè)$a="1111";$b=&$a;它的變換如下圖
$a="111"

$b=&$a;

可能有朋友注意到了,在zend_reference中refcount為2 ,但是在最后的真實(shí)的zend_value為refcount為1,這是為什么呢,其實(shí)很好理解,前面說過,refcount表示有多少個(gè)zval指向該zend_value,zend_reference中只有一個(gè)zval指向了zend_value。
中間加一層zend_reference這樣做其實(shí)有很多好處,這樣可以保留原有的zend_value類型不變,為深拷貝操作提供拷貝條件,下面我們舉個(gè)例子就知道了

是不是一目了然,只能說開發(fā)內(nèi)核的那些神牛太牛逼了。。。。。。。

當(dāng)然關(guān)于php中值傳遞不僅僅那么簡單,還有很多很復(fù)雜的東西,小菜我也是才看沒多久,望各位大牛勿噴

php中的COW (copy on write)

寫時(shí)復(fù)制是一種很重要的優(yōu)化手段,這里涉及到深拷貝和淺拷貝的知識(shí),請移步。

關(guān)于深拷貝,剛剛上面的這個(gè)例子就是很好的說明

所謂深拷貝就是將原有的數(shù)據(jù)拷貝一份放到獨(dú)立分配一個(gè)地址空間。
而寫時(shí)賦值就是對深拷貝的一種優(yōu)化吧,意思是只有當(dāng)發(fā)生寫操作的時(shí)候才進(jìn)行深拷貝

舉個(gè)例子:

$a="3333";
$b=$a;

$b.="444";

$a="3333";
$b=$a;
這個(gè)操作會(huì)使兩個(gè)zval指向同一個(gè)zend_value
這里并沒有觸發(fā)COW,執(zhí)行深拷貝

當(dāng)$b.="444";發(fā)生了寫操作的時(shí)候,觸發(fā)COW,執(zhí)行深拷貝,拷貝了完全一樣的一份zend_value,$b所在的zval由原來的和$a所在的zval共同指向之前的zend_value, 轉(zhuǎn)換成指向拷貝出的新的zend_value

如果不進(jìn)行深拷貝的話,那么當(dāng)執(zhí)行$b.="444";后,$a也會(huì)等于“3333444”

當(dāng)然不是所有的zend_value類型都可以進(jìn)行復(fù)制,這個(gè)請參見我之前的那個(gè)zend_uchar type_flags表

**文章中可能有些不足的地方,懇求指正。
本來打算再寫寫GC回收的原理的,但是現(xiàn)在已經(jīng)2點(diǎn)多了,23333333.明天還要繼續(xù)打碼呢。。。。。。。不好意思**

下一篇準(zhǔn)備寫一下php中的數(shù)組的實(shí)現(xiàn);

lift needs art,i need girl


本文參考

http://bbs.csdn.net/topics/39...

http://blog.csdn.net/black_ox...
http://blog.csdn.net/xiaolei1...
https://segmentfault.com/a/11...
https://github.com/laruence/p...
https://www.cnblogs.com/ohmyg...

可能有遺漏的參考博客,望博主見諒

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/28175.html

相關(guān)文章

  • php內(nèi)核閱讀(2)--淺談 gc回收機(jī)制

    摘要:垃圾回收所謂垃圾就是指通過循環(huán)引用自己引用自己,目前只在類型中有出現(xiàn)的形式而導(dǎo)致永遠(yuǎn)不為。當(dāng)出現(xiàn)垃圾之后,的引擎有對應(yīng)的垃圾回收機(jī)制。觸發(fā)這個(gè)機(jī)制的時(shí)機(jī)是每次出現(xiàn)減少時(shí)候。 自嘲)。。。。。2333,我覺得這是因?yàn)樵趐hp語言層面就幫我們解決了內(nèi)存回收的問題,但這讓我在和java大牛們吹牛逼的時(shí)候,聽到什么內(nèi)存泄露。。。。(納尼,我tmd怎么從來沒遇見過)一臉懵逼。 本人小菜,如果下面...

    wemallshop 評論0 收藏0
  • (PHP7內(nèi)核剖析-3) 變量

    摘要:插入一個(gè)元素時(shí)先將元素按先后順序插入數(shù)組,位置是,再根據(jù)的哈希值映射到散列表中的某個(gè)位置,將存入這個(gè)位置查找時(shí)先在散列表中映射到,得到在數(shù)組的位置,再從數(shù)組中取出元素。目前只有兩種類型會(huì)使用這種機(jī)制。 1.變量結(jié)構(gòu) typedef struct _zval_struct zval; typedef union _zend_value { zend_long ...

    RiverLi 評論0 收藏0
  • PHP7擴(kuò)展開發(fā)(三):參數(shù)、數(shù)組Zvals

    摘要:告訴引擎要取的參數(shù)的信息,用來確保線程安全,返回值檢測是還是。數(shù)組遍歷假設(shè)我們需要一個(gè)取代以下功能的擴(kuò)展的遍歷數(shù)組和差很多,提供了一些專門的宏來遍歷元素或。是一個(gè)關(guān)于線程安全的動(dòng)作,用于避免各線程的作用域被其他的侵入。 起步 到這已經(jīng)能聲明簡單函數(shù),返回靜態(tài)或者動(dòng)態(tài)值了。定義INI選項(xiàng),聲明內(nèi)部數(shù)值或全局?jǐn)?shù)值。本章節(jié)將介紹如何接收從調(diào)用腳本(php文件)傳入?yún)?shù)的數(shù)值,以及 PHP內(nèi)核...

    hufeng 評論0 收藏0
  • PHP7源碼分析】如何理解PHP虛擬機(jī)(一)

    摘要:操作數(shù)本身并無數(shù)據(jù)類型,它的數(shù)據(jù)類型由操作碼確定任何架構(gòu)的計(jì)算機(jī)都會(huì)對外提供指令集合運(yùn)算器通過執(zhí)行指令直接發(fā)出控制信號(hào)控制計(jì)算機(jī)各項(xiàng)操作。 順風(fēng)車運(yùn)營研發(fā)團(tuán)隊(duì) 李樂 1.從物理機(jī)說起 虛擬機(jī)也是計(jì)算機(jī),設(shè)計(jì)思想和物理機(jī)有很多相似之處; 1.1馮諾依曼體系結(jié)構(gòu) 馮·諾依曼是當(dāng)之無愧的數(shù)字計(jì)算機(jī)之父,當(dāng)前計(jì)算機(jī)都采用的是馮諾依曼體系結(jié)構(gòu);設(shè)計(jì)思想主要包含以下幾個(gè)方面: 指令和數(shù)據(jù)不加區(qū)別...

    tunny 評論0 收藏0
  • 徹底搞懂 PHP 變量結(jié)構(gòu)體,多數(shù)文章觀點(diǎn)不準(zhǔn)確

    摘要:中的用于類型整型和資源類型用于浮點(diǎn)類型用于字符串用于數(shù)組用于對象用于常量表達(dá)式才有多數(shù)文章,在提到變量結(jié)構(gòu)體的時(shí)候,都提到,實(shí)際上這個(gè)論述并不準(zhǔn)確,在為時(shí),這個(gè)結(jié)果是正確的。主要看中的,是兩個(gè),這個(gè)永遠(yuǎn)是個(gè)字節(jié),所以,因此。 PHP5 中的 zval // 1. zval typedef struct _zval_struct { zvalue_value value; ...

    mtunique 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<