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长度申请内存 };
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 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
typedef struct _zend_reference zend_reference; struct _zend_reference { zend_refcounted_h gc; zval val; };
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)
$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. Referenzbeziehung vor dem Unscharfschalten ($a):
Nach dem Unscharfschalten ($a):
$a = [1]; $a[] = &$a; unset($a);
PHP7 Kernel Analysis 1 CGI und FastCGI
PHP7 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!