Heim >Backend-Entwicklung >PHP-Tutorial >Variablen der PHP7-Kernelanalyse 3

Variablen der PHP7-Kernelanalyse 3

不言
不言Original
2018-04-13 14:54:041518Durchsuche

Der Inhalt dieses Artikels handelt von PHP7 Kernel Analysis 1 CGI und FastCGI. Jetzt können Freunde in Not darauf verweisen

typedef struct _zval_struct     zval;

typedef union _zend_value {
    zend_long         lval;    //int整形
    double            dval;    //浮点型
    zend_string      *str;     //string字符串
    zend_array       *arr;     //array数组
    zend_object      *obj;     //object对象
    zend_resource    *res;     //resource资源类型
    zend_reference   *ref;     //引用类型,通过&$var_name定义的
} zend_value;

struct _zval_struct {
    zend_value        value; //变量实际的value
    union {
        struct {
            ZEND_ENDIAN_LOHI_4( 
                zend_uchar    type,         //变量类型
                zend_uchar    type_flags,  //类型掩码,不同的类型会有不同的几种属性,内存管理会用到
                zend_uchar    const_flags,
                zend_uchar    reserved)
        } v;
        uint32_t type_info; //上面4个值的组合值,可以直接根据type_info取到4个对应位置的值
    } u1;
    union {
        uint32_t     var_flags;
        uint32_t     next;  //哈希表中解决哈希冲突时用到   
        uint32_t     cache_slot;   
        uint32_t     lineno;    
        uint32_t     num_args;    
        uint32_t     fe_pos;  
        uint32_t     fe_iter_idx;
    } u2;
};


2. Variablentyp

wobei undef, true, false und null keinen Wert haben und direkt basieren Beim Typ Distinguish werden Long- und Double-Werte direkt im Wert gespeichert, andere Typen sind Zeiger

#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


3

typedef struct _zend_string   zend_string;

struct _zend_string {
    zend_refcounted_h gc;  //变量引用信息,比如当前value的引用数
    size_t            len;  //字符串长度,通过这个值保证二进制安全
    char              val[1]; //字符串内容,变长struct,分配时按len长度申请内存
};
4. Array


HashTable verlässt sich hauptsächlich auf arData, um die Speicherung und Indizierung von Elementen zu implementieren. Wenn Sie ein Element einfügen, fügen Sie es zuerst der Reihe nach in das Bucket-Array ein. Die Position ist idx. Ordnen Sie es dann entsprechend dem Hash-Wert des Schlüssels einer bestimmten Position nIndex in der Hash-Tabelle zu und speichern Sie idx an dieser Position. Rufen Sie bei der Suche zunächst die Hash-Tabelle Map to nIndex auf, ermitteln Sie die Positions-IDX des Werts im Bucket-Array und entnehmen Sie dann das Element aus dem Bucket-Array.

typedef struct _zend_array HashTable;
typedef struct _zend_array zend_array;

typedef struct _Bucket {
    zval              val; //存储的具体value,这里嵌入了一个zval,而不是一个指针
    zend_ulong        h;   //哈希值
    zend_string      *key; //key值
} Bucket;

struct _zend_array {
    zend_refcounted_h gc; //引用计数信息
    uint32_t          nTableMask;  //计算bucket索引时的掩码,用于散列表的计算nIndex
    Bucket           *arData;     //bucket数组
    uint32_t          nNumUsed;   //已用bucket数
    uint32_t          nNumOfElements; //已有元素数,nNumOfElements <= nNumUsed,因为删除的并不是直接从arData中移除
    uint32_t          nTableSize; //数组的大小,为2^n,默认为8
    uint32_t          nInternalPointer; //数值索引,用于HashTable遍历
    zend_long         nNextFreeElement;//下一个空闲可用位置的数字索引
    dtor_func_t       pDestructor;//析构函数,销毁时调用的函数指针
};
$arr["a"] = 1;
$arr["b"] = 2;
$arr["c"] = 3;
$arr["d"] = 4;

unset($arr["c"]);

Hash-Kollision: Wenn ein Konflikt auftritt, speichern Sie die Position des ursprünglichen Werts in zval.u2.next des neuen Werts. und dann Ersetzen Sie die ursprüngliche Wertposition durch den neuen Wert Variablen der PHP7-Kernelanalyse 3 Erweiterung: Die Größe der PHP-Hash-Tabelle beträgt 2^n. Wenn die Kapazität beim Einfügen nicht ausreicht, wird zunächst der Anteil der gelöschten Elemente überprüft. Wenn der Schwellenwert erreicht ist, werden die gelöschten Elemente verschoben. Wenn der Schwellenwert nicht erreicht wird, führen Sie einen Erweiterungsvorgang auf das Zweifache der aktuellen Größe durch, kopieren Sie das aktuelle Bucket-Array in einen neuen Bereich und erstellen Sie ihn dann neu der Index.

Erstellen Sie die Hash-Tabelle neu: Wenn die gelöschten Elemente eine bestimmte Anzahl erreichen oder die Kapazität erweitert wird, muss die Hash-Tabelle neu erstellt werden, da sich der Wert in der Bucket-Position verschoben hat oder sich die nTableSize des Hash-Arrays geändert hat, was dazu führt Die Zuordnungsbeziehung zwischen Schlüssel und Wert wird geändert. Der eigentliche Prozess besteht darin, die Werte im Bucket-Array zu durchlaufen, dann den Zuordnungswert neu zu berechnen und in der Hash-Tabelle zu aktualisieren, den gelöschten Wert zu entfernen und den nachfolgenden zu verschieben Nicht gelöschte Werte werden der Reihe nach weitergeleitet.
5. Referenz


Referenz ist ein spezieller Typ in PHP Durch Ändern der PHP-Variable wird der tatsächlich angezeigte zval einfach als Zeiger verstanden. In PHP wird eine Referenzvariable durch den &-Operator generiert. & erstellt zunächst eine zend_reference-Struktur mit einem darin eingebetteten zval. Der Wert dieses zval zeigt auf den ursprünglichen Wert von zval (wenn es sich um einen Booleschen Wert, eine Ganzzahl oder einen Gleitkommawert handelt, kopieren Sie den ursprünglichen Wert direkt) und ändern Sie ihn dann Der Typ des ursprünglichen zval auf IS_REFERENCE und der Wert des ursprünglichen zval zeigt auf die neu erstellte zend_reference-Struktur.

typedef struct _zend_reference  zend_reference;

struct _zend_reference {
    zend_refcounted_h gc;
    zval              val;
};
6. Referenzzählung


Nicht alle Datentypen verwenden Referenzzählung, lange und double sind direkte Hardcopys. Nur die Typen, deren Wert ein Zeiger ist (außer internierte Zeichenfolgen und unveränderliche Arrays), können die Referenzzählung verwenden. Es kann durch zval.u1.type_flag

typedef struct _zend_refcounted_h {
    uint32_t         refcount;         
    union {
        struct {
            ZEND_ENDIAN_LOHI_3(
                zend_uchar    type,
                zend_uchar    flags,   
                uint16_t      gc_info)  
        } v;
        uint32_t type_info;
    } u;
} zend_refcounted_h;
$a = "time:" . time();   //$a       ->  zend_string_1(refcount=1)
$b = $a;                 //$a,$b    ->  zend_string_1(refcount=2)
$c = $b;                 //$a,$b,$c ->  zend_string_1(refcount=3)

unset($b);               //$b = IS_UNDEF  $a,$c ->  zend_string_1(refcount=2)
7 bestimmt werden >


Tatsächlich werden nur String und Array unterstützt,

$a = array(1,2);
$b = &$a;
$c = $a;

//发生分离
$b[] = 3;

8 >PHP-Variablen Es gibt zwei Hauptarten des Recyclings: aktive Zerstörung und automatische Zerstörung. Aktive Zerstörung bezieht sich auf Unset, und automatische Zerstörung ist der automatische Verwaltungsmechanismus von PHP. Auch wenn keine explizite Rückgabe erfolgt, fügt PHP diesen Vorgang automatisch hinzu. Wenn auf den ursprünglichen Wert verwiesen wird, wird auch der Refcount des alten Werts nach der Trennung überprüft. Variablen der PHP7-Kernelanalyse 3Referenzbeziehung vor dem Unscharfschalten ($a):


Nach dem Unscharfschalten ($a):

$a = [1];
$a[] = &$a;

unset($a);

Verwandte Empfehlungen:

Variablen der PHP7-Kernelanalyse 3

PHP7 Kernel Analysis 1 CGI und FastCGI

Variablen der PHP7-Kernelanalyse 3PHP7 Kernel Analysis 2 I/O-Modell

Das obige ist der detaillierte Inhalt vonVariablen der PHP7-Kernelanalyse 3. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn