ホームページ > バックエンド開発 > PHPチュートリアル > PHP カーネルの研究: HASH テーブルと変数_PHP チュートリアル

PHP カーネルの研究: HASH テーブルと変数_PHP チュートリアル

WBOY
リリース: 2016-07-14 10:08:25
オリジナル
892 人が閲覧しました

PHPハッシュテーブル

PHP では、変数、定数、クラス、属性に関係なく、すべてのデータはハッシュ テーブルを使用して実装されます。
まず HASH テーブルについて話しましょう
typedef 構造体バケット {
ulong h;
uint nKeyLength; //キーの長さ
void *pData; // Bucke によって保存されたデータへのポインタ
void *pDataPtr; //ポインタデータ
struct Bucket *pListNext //次の要素ポインタ
structbucket *pListLast; //前の要素ポインタ
構造体バケット *pNext
構造体バケット *pLast;
char arKey[1] /* 最後の要素である必要があります */
} バケツ
typedef struct _hashtable {
uint nTableSize //ハッシュテーブルのサイズ
uint nTableMask;//nTableSize-1 と等しい
uint nNumOfElements;//オブジェクトの数
ulong nNextFreeElement //次の空の要素の位置を指す nTableSize+1
Bucket *pInternalPointer; /* 要素の走査に使用されます */// 現在の走査されたポインターを保存します
Bucket *pListHead;//ヘッド要素ポインタ
Bucket *pListTail;//末尾要素ポインタ
Bucket **arBuckets;//ストレージのハッシュ配列データ
dtor_func_t pDestructor;//デストラクターに似ています
zend_boolpersistent;//PHP はメモリを均一に管理するのか、それとも通常の malloc を使用するのか
unsigned char nApplyCount;//現在のハッシュ バケットがアクセスされた回数、無限再帰ループを防ぐためにデータが走査されたかどうか
zend_bool bApplyProtection;
#if ZEND_DEBUG
一貫性がありません
#endif
} ハッシュテーブル
HASHテーブル初期化関数と組み合わせてみましょう
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool 永続 ZEND_FILE_LINE_DC)
{
uint i = 3;
バケツ**tmp;
SET_INCONSISTENT(HT_OK);
if (nSize >= 0x80000000) { //HASH テーブルのサイズが 0x8 より大きい場合、0x8 に初期化されます
/* オーバーフローを防ぐ */
ht->nTableSize = 0x80000000;
} その他 {
while ((1U << i) < nSize) { //2 の n 乗に調整 i++; i++ Power i=3、nTableSize の最小値は 8 です
}
//計算効率を向上させるために、システムは nTableSize を nTableSize 以上の最小の 2 の整数乗に自動的に調整します。つまり、HashTable の初期化時に 2 の整数乗ではない nTableSize を指定すると、システムは nTableSize の値を自動的に調整します。
ht->nTableMask = ht->nTableSize - 1;
ht->pDestructor = pDestructor;//HashTable が追加、削除、または変更されたときに呼び出される関数ポインター
ht->arBuckets = NULL;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
ht->nNextFreeElement = 0;
ht->pInternalPointer = NULL;
ht->persistent =persistent; //persistent が TRUE の場合は、オペレーティング システム独自のメモリ割り当て関数を使用してバケットにメモリを割り当てます。それ以外の場合は、PHP のメモリ割り当て関数を使用します
ht->nApplyCount = 0;
ht->bApplyProtection = 1;
/* ecalloc() を使用して、Bucket* == NULL */
if (persistent) { //オペレーティング システムは、独自のメモリ割り当てメソッドを使用してメモリを割り当てます。calloc がメモリを割り当てた後、メモリは自動的に 0 に初期化されます。
tmp = (バケット **) calloc(ht->nTableSize, sizeof(バケット *));
if (!tmp) {
失敗を返す
}
ht->arBuckets = tmp;
} else {//PHP のメモリ管理メカニズムを使用してメモリを割り当てます
tmp = (バケット **) ecalloc_rel(ht->nTableSize, sizeof(バケット *));
if (tmp) {
ht->arBuckets = tmp;
}
}
//arBuckets のメモリを自動的に適用します。メモリ サイズは nTableSize と同じです
成功を返す
}
ソースコードを読んでいると、EG、PG、CGなどのマクロをよく見かけます
CGはcompile_globalの略です
EGはexcutor_globalの略称です
Gはグローバル変数を意味します
EGマクロを例に見てみましょう
#ifdef ZTS
# EG(v) TSRMG(executor_globals_id, zend_executor_globals *, v) を定義します
#その他
# EG(v) (executor_globals.v) を定義します
extern ZEND_API zend_executor_globals executor_globals
#endif
とてもシンプルで、グローバル変数を取得するマクロだけです
それでは、zend_executor_globals 構造体を見てみましょう
/Zend/zend.h で定義
typedef struct _zend_executor_globals zend_executor_globals;
は _zend_executor_globals のエイリアスです
同じファイル内で見つかりました
PHPのすべてのローカル変数、グローバル変数、関数、クラスハッシュテーブルはここで定義されています
struct _zend_executor_globals {
zval **return_value_ptr_ptr;
zval uninitialized_zval
zval *uninitialized_zval_ptr;
zval エラー_zval
zval *error_zval_ptr;
zend_ptr_stack arg_types_stack;
/* シンボル テーブル キャッシュ */
ハッシュテーブル *symtable_cache[SYMTABLE_CACHE_SIZE]
ハッシュテーブル **symtable_cache_limit
ハッシュテーブル **symtable_cache_ptr;
zend_op **opline_ptr;
HashTable *active_symbol_table //ローカル変数
HashTablesymbol_table; /* メインシンボルテーブル */ //グローバル変数
HashTable Included_files; /* ファイルはすでにインクルードされています */ // ファイルをインクルードします
JMP_BUF *救済
int エラー報告
int orig_error_reporting
int 終了ステータス
zend_op_array *active_op_array
HashTable *function_table; /* 関数シンボルテーブル */ //関数テーブル
HashTable *class_table; /* クラステーブル */ //クラステーブル
HashTable *zend_constants; /* 定数テーブル */ // 定数テーブル
zend_class_entry *スコープ;
zend_class_entry *named_scope; /* 呼び出し元クラスのスコープ */
zval *これ;
長い精度
int ティック数
zend_bool in_execution
ハッシュテーブル *in_autoload
zend_function *autoload_func
zend_bool full_tables_cleanup
/* 拡張情報サポート用 */
zend_bool no_extensions
#ifdef ZEND_WIN32
zend_bool がタイムアウトしました
OSVERSIONINFOEX Windows_version_info
#endif
ハッシュテーブルの正規リスト
ハッシュテーブル永続リスト
zend_vm_stack 引数_スタック
int user_error_handler_error_reporting
zval *user_error_handler
zval *ユーザー例外ハンドラー
zend_stack user_error_handlers_error_reporting
zend_ptr_stack user_error_handlers
zend_ptr_stack ユーザー例外ハンドラー
zend_error_handling_t エラー処理
zend_class_entry *例外クラス
/* タイムアウトのサポート */
int タイムアウト_秒
int ラムダ数
ハッシュテーブル *ini_directives;
ハッシュテーブル *modified_ini_directives;
zend_objects_store オブジェクトストア
zval *例外、*prev_例外
zend_op *opline_before_例外
zend_op 例外_op[3];
struct _zend_execute_data *current_execute_data
struct_zend_module_entry *current_module;
zend_property_info std_property_info;
zend_bool がアクティブです。
void *saved_fpu_cw;
無効 *予約済み[ZEND_MAX_RESERVED_RESOURCES]
};
まずはここで簡単に見てみましょう。後で使用するときに詳しく説明します
PHP の最も基本的な単位は変数です:
PHP で変数を定義するのはこれ以上に簡単です
として
$a=1;
?>
ただし、カーネルでは zval 構造で実装されます
変数が上記で定義されている場合、次のコードがカーネルで実行されます
zval *val
MAKE_STD_ZVAL(val); // メモリを申請します
ZVAL_STRING(val,"hello",1);//ZVAL_STRING を使用して値を「hello」に設定します
ZEND_SET_SYMBOL(EG(active_symbol_table),"a",val));//val ポインタをシンボルテーブルに追加します
マクロMAKE_STD_ZVALは次のように定義されています
#define MAKE_STD_ZVAL(zv)
ALLOC_ZVAL(zv); //最終的には (p) = (type *) emalloc(sizeof(type)) と等しくなります
INIT_PZVAL(zv);
INIT_PZVAL は
で定義されています
#define INIT_PZVAL(z) 初期化パラメータであることがわかります
(z)->refcount__gc = 1;
(z)->is_ref__gc = 0;
それでは、zvalとは何ですか
zend/zend.h 内
typedef struct _zval_struct zval; // _zval_struct のエイリアスであることが判明
_zval_structは次のように定義されています
typedef Union _zvalue_value {
long lval; //long 型データを保存する
double dval; //double 型のデータを保存します
構造体{
char *val // 本当の値はここにあります
; Int len // ここに長さを返します
}
ハッシュテーブル*ht;
zend_object_value obj // これはオブジェクトです
;
} zvalue_value
struct _zval_struct {
zvalue_value 値 // 保存された値
zend_uint refcount__gc;// 1 の場合は単独でのみ使用され、1 より大きい場合は
の形式で他の変数から参照されます。
zend_uchar type; //データ型 これが、PHP の型指定が弱い理由です
zend_uchar is_ref__gc; // 参照であるかどうかを示します
};
まだ十分に理解できない場合は...試してみましょう...C を使用して PHP 変数を作成します
ここでは拡張機能が必要です。PHP が C 拡張モジュールを使用する場合は、ここでは詳しく説明しません
キーコード
PHP_FUNCTION(test_siren){
zval *value;
char *s="PHP 変数を作成する";
値=(zval*)malloc(sizeof(zval));
memset(値,0,サイズ(値));
value->is_ref__gc=0; //非参照変数
Value->refcount__gc=1;//引用数 自分のみ
value->type=IS_STRING;// 型は文字列です
value->value.str.val=s;//value
value->value.str.len=strlen(s);//長さ
ZEND_SET_SYMBOL(EG(active_symbol_table),"a",value);
}
3行目と4行目はMAKE_STD_ZVALと同じ機能で、値にメモリ空間を割り当てます
5行目から9行目までの機能はZVAL_STRINGの機能と同じです
最後の行は、値として PHP で $a という変数を作成し、それをローカルのハッシュ テーブルに追加することです。
PHPではこうする
テストサイレン(1);
エコー $a
?>
「php変数の作成」と出力されます
わかりました、
完了
注、私は PHP 内で変数を作成するプロセスを皆さんに見てもらうためだけに、C 形式で変数を作成しました。
これを行うことは絶対に推奨されません。
メモリの割り当てと処理には、引き続き PHP の内部メモリ管理メカニズムを使用する必要があります。
http://www.bkjia.com/PHPjc/477783.html

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/477783.html技術記事 PHP HASH テーブル PHP では、変数、定数、クラス、属性に関係なく、すべてのデータがハッシュ テーブルを使用して実装されます。まず、HASH テーブルについて説明します。 typedef structbucket { /* 数値インデックスに使用されます */ ui。 ..
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート