Le contenu de cet article présente CGI et FastCGI sur l'analyse du noyau PHP7 1. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent s'y référer
1. >
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; };
où undef, true, false et null n'ont aucune valeur et sont directement basés sur la distinction des types, tandis que les valeurs de long et double sont directement stockées dans value, et les autres types sont des pointeurs
#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
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 s'appuie principalement sur arData pour implémenter le stockage et l'indexation des éléments. Lors de l'insertion d'un élément, insérez d'abord l'élément dans le tableau Bucket dans l'ordre, la position est idx, puis mappez-le à une certaine position nIndex dans la table de hachage en fonction de la valeur de hachage de la clé, et stockez idx dans cette position ; lors de la recherche, d'abord dans la table de hachage Map to nIndex, obtenez la position idx de la valeur dans le tableau Bucket, puis supprimez l'élément du tableau Bucket.
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"]);
Collision de hachage : lorsqu'un conflit se produit, enregistrez la position de la valeur d'origine dans zval.u2.next de la nouvelle valeur, puis Remplacez la position de la valeur d'origine par la nouvelle valeur Expansion : La taille de la table de hachage PHP est de 2^n Si la capacité n'est pas suffisante lors de l'insertion, la proportion d'éléments supprimés sera d'abord vérifiée. Si le seuil est atteint, les éléments supprimés seront déplacés et reconstruiront l'index. Si le seuil n'est pas atteint, effectuez une opération d'expansion jusqu'à 2 fois la taille actuelle, copiez le tableau Bucket actuel dans un nouvel espace, puis reconstruisez. l'indice.
Reconstruire la table de hachage : lorsque les éléments supprimés atteignent un certain nombre ou que la capacité est augmentée, la table de hachage doit être reconstruite car la valeur s'est déplacée dans la position du compartiment ou le tableau de hachage nTableSize a changé, provoquant la relation de mappage entre la clé et la valeur à modifier.Le processus de reconstruction Le processus réel consiste à parcourir les valeurs dans le tableau Bucket, puis à recalculer la valeur de mappage et à la mettre à jour dans la table de hachage, à supprimer la valeur supprimée et à déplacer la valeur suivante. les valeurs non supprimées sont transmises dans l'ordre
5. Référence
La référence est un type spécial en PHP. Elle pointe en fait vers un autre. Variable PHP. La modifier modifiera directement le zval réellement pointé. Elle peut être simplement comprise comme un pointeur en C, une variable de référence est générée via l'opérateur & en PHP. & créera d'abord une structure zend_reference avec un zval intégré. La valeur de ce zval pointe vers la valeur originale de zval (s'il s'agit d'un booléen, d'un entier ou d'un virgule flottante, copiez directement la valeur d'origine), puis modifiez-la. le type du zval d'origine est IS_REFERENCE et la valeur du zval d'origine pointe vers la structure zend_reference nouvellement créée.
typedef struct _zend_reference zend_reference; struct _zend_reference { zend_refcounted_h gc; zval val; };
6. Comptage de références
Tous les types de données n'utilisent pas de références, long. et double sont directement des copies papier. Seuls les types dont la valeur est un pointeur (sauf chaîne interne, tableau immuable) peuvent utiliser le comptage de références. Il peut être déterminé par 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 Copie en écriture
<🎜. >
$a = array(1,2); $b = &$a; $c = $a; //发生分离 $b[] = 3;
En fait, seules les chaînes et les tableaux sont pris en charge,
Collecte des déchets
<🎜. >Variables PHP Il existe deux grands types de recyclage : la destruction active et la destruction automatique. La destruction active fait référence à unset, et la destruction automatique est le mécanisme de gestion automatique de PHP.Lors du retour, le refcount des variables locales est soustrait Même s'il n'y a pas de retour explicite, PHP ajoutera automatiquement cette opération. Lorsque la valeur d'origine est déconnectée, le refcount de l'ancienne valeur après la déconnexion sera également vérifié.
Relation de référence avant la désactivation ($a) :
$a = [1]; $a[] = &$a; unset($a);
Recommandations associées :
Analyse du noyau PHP7 1 CGI et FastCGI
Modèle d'E/S d'analyse du noyau PHP7 2
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!