Heim php教程 php手册 PHP内核研究:HASH表和变量

PHP内核研究:HASH表和变量

Jun 13, 2016 am 10:54 AM
hash php Kernel 变量 existieren 属性 常量 数据 研究

PHP HASH表

 

在PHP中,所有的数据 无论变量,常量,类,属性 都用Hash表来实现.

 

先要说说 HASH表

 

 

 

typedef struct bucket { 

        ulong h;                                                /* Used for numeric indexing */ 

        uint nKeyLength; //key长度 

        void *pData; //指向 Bucke保存的数据 指针 

        void *pDataPtr; //指针数据 

        struct bucket *pListNext; //下一个元素指针 

        struct bucket *pListLast;//上一个元素指针 

        struct bucket *pNext; 

        struct bucket *pLast; 

        char arKey[1]; /* Must be last element */ 

} Bucket; 

typedef struct _hashtable { 

        uint nTableSize;//HashTable的大小 

        uint nTableMask;//等于nTableSize-1 

        uint nNumOfElements;//对象个数 

        ulong nNextFreeElement;//指向下一个空元素位置 nTableSize+1 

        Bucket *pInternalPointer;       /* Used for element traversal *///保存当前遍历的指针 

        Bucket *pListHead;//头元素指针 

        Bucket *pListTail;//尾元素指针 

        Bucket **arBuckets;//存储hash数组数据 

        dtor_func_t pDestructor;//类似于析构函数 

        zend_bool persistent;//用哪种方法分配内存空间 PHP统一管理内存还是用普通的malloc 

        unsigned char nApplyCount;//当前hash bucket被访问的次数,是否遍历过数据,防止无限递归循环 

        zend_bool bApplyProtection; 

#if ZEND_DEBUG 

        int inconsistent; 

#endif 

} HashTable; 

我们结合 HASH表初始化函数来说

 

ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) 

 uint i = 3; 

 Bucket **tmp; 

  

SET_INCONSISTENT(HT_OK); 

  

 if (nSize >= 0x80000000) { //HASH表大小大于0x8则初始化为0x8 

       /* prevent overflow */ 

       ht->nTableSize = 0x80000000; 

 } else { 

       while ((1U nTableSize = 1

 } 

//为了提高计算效率,系统自动会将nTableSize调整到最小一个不小于nTableSize的2的整数次方。也就是说,如果在初始化HashTable时指定一个nTableSize不是2的整数次方,系统将会自动调整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;//如果persisient为TRUE,则使用操作系统本身的内存分配函数为Bucket分配内存,否则使用PHP的内存分配函数 

 ht->nApplyCount = 0; 

 ht->bApplyProtection = 1; 

  

 /* Uses ecalloc() so that Bucket* == NULL */ 

 if (persistent) {  //操作系统本身内存分配方式分配内存,calloc分配内存后自动初始化为0 

 tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *)); 

 if (!tmp) { 

 return FAILURE; 

 } 

 ht->arBuckets = tmp; 

 } else {//用PHP的内存管理机制分配内存 

 tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *)); 

 if (tmp) { 

 ht->arBuckets = tmp; 

 } 

 } 

//自动申请一块内存给arBuckets,该内存大小等于 nTableSize 

return SUCCESS; 

 

    在读源码的时候 ,经常会看到 EG,PG,CG这样的宏

CG是 compile_global的简写

 

EG是excutor_global的简写

 

G就是全局变量的意思

 

我们就以EG宏为例

 

 

 

#ifdef ZTS 

# define EG(v) TSRMG(executor_globals_id, zend_executor_globals *, v) 

#else 

# define 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的所有 局部变量,全局变量,函数,类的 Hash表 都在这里定义了

 

 

 

struct _zend_executor_globals { 

zval **return_value_ptr_ptr; 

  

zval uninitialized_zval; 

zval *uninitialized_zval_ptr; 

  

zval error_zval; 

zval *error_zval_ptr; 

  

zend_ptr_stack arg_types_stack; 

  

/* symbol table cache */ 

HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; 

HashTable **symtable_cache_limit; 

HashTable **symtable_cache_ptr; 

  

zend_op **opline_ptr; 

  

HashTable *active_symbol_table;  //局部变量 

HashTable symbol_table; /* main symbol table */ //全局变量 

  

HashTable included_files; /* files already included */ //include的文件 

  

JMP_BUF *bailout; 

  

int error_reporting; 

int orig_error_reporting; 

int exit_status; 

  

zend_op_array *active_op_array; 

  

HashTable *function_table; /* function symbol table */ //函数表 

HashTable *class_table; /* class table */ //类表 

HashTable *zend_constants; /* constants table */ //常量表 

  

zend_class_entry *scope; 

zend_class_entry *called_scope; /* Scope of the calling class */ 

  

zval *This; 

  

long precision; 

  

int ticks_count; 

  

zend_bool in_execution; 

HashTable *in_autoload; 

zend_function *autoload_func; 

zend_bool full_tables_cleanup; 

  

/* for extended information support */ 

zend_bool no_extensions; 

  

#ifdef ZEND_WIN32 

zend_bool timed_out; 

OSVERSIONINFOEX windows_version_info; 

#endif 

  

HashTable regular_list; 

HashTable persistent_list; 

  

zend_vm_stack argument_stack; 

  

int user_error_handler_error_reporting; 

zval *user_error_handler; 

zval *user_exception_handler; 

zend_stack user_error_handlers_error_reporting; 

zend_ptr_stack user_error_handlers; 

zend_ptr_stack user_exception_handlers; 

  

zend_error_handling_t error_handling; 

zend_class_entry *exception_class; 

  

/* timeout support */ 

int timeout_seconds; 

  

int lambda_count; 

  

HashTable *ini_directives; 

HashTable *modified_ini_directives; 

  

zend_objects_store objects_store; 

zval *exception, *prev_exception; 

zend_op *opline_before_exception; 

zend_op exception_op[3]; 

  

struct _zend_execute_data *current_execute_data; 

  

struct _zend_module_entry *current_module; 

  

zend_property_info std_property_info; 

  

zend_bool active; 

  

void *saved_fpu_cw; 

  

void *reserved[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类型的数据 

        struct { 

                char *val; //真正的值在这里 

                int len;   //这里返回长度 

        } str; 

        HashTable *ht; 

        zend_object_value obj; //这是一个对象 

} zvalue_value; 

  

struct _zval_struct { 

zvalue_value 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="create a php variable"; 

        value=(zval*)malloc(sizeof(zval)); 

        memset(value,0,sizeof(value)); 

        value->is_ref__gc=0; //非引用变量 

        value->refcount__gc=1;//引用次数 只有自己 

        value->type=IS_STRING;//类型为字符串 

        value->value.str.val=s;//值 

        value->value.str.len=strlen(s);//长度 

        ZEND_SET_SYMBOL(EG(active_symbol_table),"a",value); 

第三行和第四行的作用 与MAKE_STD_ZVAL的作用相同,给value分配内存空间

第5-9行 的作用与ZVAL_STRING的作用相同,

最后一行 是将value创建一个 在PHP里叫$a的变量..并添加到局部Hash表里..

这样 在PHP里

 

 

 

test_siren(1); 

echo $a; 

?> 

就会输出 “create a php variable”

OK,

大功告成

注意,我是为了让大家看到PHP内部创建变量的流程 才采用C的形式创建变量,

绝对不推荐大家这样做.

还是一定要用PHP内部的内存管理机制分配并处理内存。

 

 

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

PHP 8.4 Installations- und Upgrade-Anleitung für Ubuntu und Debian PHP 8.4 Installations- und Upgrade-Anleitung für Ubuntu und Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 bringt mehrere neue Funktionen, Sicherheitsverbesserungen und Leistungsverbesserungen mit einer beträchtlichen Menge an veralteten und entfernten Funktionen. In dieser Anleitung wird erklärt, wie Sie PHP 8.4 installieren oder auf PHP 8.4 auf Ubuntu, Debian oder deren Derivaten aktualisieren. Obwohl es möglich ist, PHP aus dem Quellcode zu kompilieren, ist die Installation aus einem APT-Repository wie unten erläutert oft schneller und sicherer, da diese Repositorys in Zukunft die neuesten Fehlerbehebungen und Sicherheitsupdates bereitstellen.

CakePHP Datum und Uhrzeit CakePHP Datum und Uhrzeit Sep 10, 2024 pm 05:27 PM

Um in cakephp4 mit Datum und Uhrzeit zu arbeiten, verwenden wir die verfügbare FrozenTime-Klasse.

Besprechen Sie CakePHP Besprechen Sie CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP ist ein Open-Source-Framework für PHP. Es soll die Entwicklung, Bereitstellung und Wartung von Anwendungen erheblich vereinfachen. CakePHP basiert auf einer MVC-ähnlichen Architektur, die sowohl leistungsstark als auch leicht zu verstehen ist. Modelle, Ansichten und Controller gu

CakePHP-Datei hochladen CakePHP-Datei hochladen Sep 10, 2024 pm 05:27 PM

Um am Datei-Upload zu arbeiten, verwenden wir den Formular-Helfer. Hier ist ein Beispiel für den Datei-Upload.

CakePHP erstellt Validatoren CakePHP erstellt Validatoren Sep 10, 2024 pm 05:26 PM

Der Validator kann durch Hinzufügen der folgenden zwei Zeilen im Controller erstellt werden.

So richten Sie Visual Studio-Code (VS-Code) für die PHP-Entwicklung ein So richten Sie Visual Studio-Code (VS-Code) für die PHP-Entwicklung ein Dec 20, 2024 am 11:31 AM

Visual Studio Code, auch bekannt als VS Code, ist ein kostenloser Quellcode-Editor – oder eine integrierte Entwicklungsumgebung (IDE) –, die für alle gängigen Betriebssysteme verfügbar ist. Mit einer großen Sammlung von Erweiterungen für viele Programmiersprachen kann VS Code c

CakePHP-Kurzanleitung CakePHP-Kurzanleitung Sep 10, 2024 pm 05:27 PM

CakePHP ist ein Open-Source-MVC-Framework. Es erleichtert die Entwicklung, Bereitstellung und Wartung von Anwendungen erheblich. CakePHP verfügt über eine Reihe von Bibliotheken, um die Überlastung der häufigsten Aufgaben zu reduzieren.

Wie analysiert und verarbeitet man HTML/XML in PHP? Wie analysiert und verarbeitet man HTML/XML in PHP? Feb 07, 2025 am 11:57 AM

Dieses Tutorial zeigt, wie XML -Dokumente mit PHP effizient verarbeitet werden. XML (Extensible Markup-Sprache) ist eine vielseitige textbasierte Markup-Sprache, die sowohl für die Lesbarkeit des Menschen als auch für die Analyse von Maschinen entwickelt wurde. Es wird üblicherweise für die Datenspeicherung ein verwendet und wird häufig verwendet

See all articles