Maison >développement back-end >tutoriel php >Analyse du noyau PHP7 3 variables

Analyse du noyau PHP7 3 variables

不言
不言original
2018-04-13 14:54:041518parcourir

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;
};


2. Type de variable

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


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 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 Analyse du noyau PHP7 3 variables 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, Analyse du noyau PHP7 3 variables

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);

Après la désactivation ($a) :

Analyse du noyau PHP7 3 variables

Recommandations associées : Analyse du noyau PHP7 3 variables

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn