この記事の内容は、PHP7 カーネル解析 1 の CGI と FastCGI についてです。必要な友達に参考にしてください。
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;
};
このうち、undef、true、false、nullは値を持たず型によって直接区別されますが、longとdoubleの値はvalueに直接格納され、その他の型はポインタになります
#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长度申请内存
};
HashTable は、要素の保存とインデックス付けを実現するために主に arData に依存します。要素を挿入するときは、まず要素を Bucket 配列に順番に挿入します。位置は idx です。次に、キーのハッシュ値に従ってハッシュ テーブル内の特定の位置 nIndex にマッピングし、この位置に idx を格納します。検索時は、まずハッシュテーブルMap to nIndexでBucket配列内のvalueの位置idxを取得し、その後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;//析构函数,销毁时调用的函数指针 };
ハッシュ衝突: 衝突が発生した場合、元の値の位置を新しい値の zval.u2.next に保存し、元の値の位置を新しい値で置き換えます
拡張: PHP ハッシュ テーブルのサイズは 2^n です。容量が足りない場合は、まず削除された要素の割合を確認します。しきい値に達した場合は、削除された要素が削除され、インデックスが再構築されます。到達していない場合は、容量を現在のサイズの 2 倍に拡張し、現在のバケット配列を新しい領域にコピーして、インデックスを再構築します。
ハッシュテーブルの再構築: 削除された要素が一定数に達した場合や容量が拡張された場合、バケットの位置で値が移動したり、ハッシュ配列nTableSizeが変更され、ハッシュテーブル間のマッピング関係が発生したりするため、ハッシュテーブルを再構築する必要があります。再構築プロセスでは、実際には配列内のバケットの値を走査し、マップされた値を再計算してハッシュ テーブルに更新し、削除された値を削除し、その後の削除されていない値を順に移動します
5. リファレンス
リファレンスは、PHP では特別です。これを変更すると、実際に指す zval が直接変更されます。PHP では、単にポインタとして理解できます。 、参照変数は & 演算子によって生成されます。つまり、前の型が何であったとしても、& は最初に zval が埋め込まれた zend_reference 構造体を作成します。この zval の値は、元の zval の値を指します。 (ブール値、整数、または浮動小数点の場合は、元の値が直接コピーされます)、その後、元の zval の型が IS_REFERENCE に変更され、元の zval の値は、新しく作成された zend_reference 構造体を指します。
$arr["a"] = 1; $arr["b"] = 2; $arr["c"] = 3; $arr["d"] = 4; unset($arr["c"]);
6. 参照カウント
typedef struct _zend_reference zend_reference; struct _zend_reference { zend_refcounted_h gc; zval val; };
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;すべてのデータ型が参照カウントを使用するわけではありません。値がポインターである型のみが参照を使用できます。数えています。 zval.u1.type_flag
7. Copy on write
実際には文字列と配列のみがサポートされています
8。
$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)unset($a) 前:
unset($a) 後:
関連する推奨事項:
PHP7 カーネル分析1 CGI と FastCGI
以上がPHP7 カーネル分析 3 変数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。