백엔드 개발 PHP 튜토리얼 PHP内核研究:HASH表和变量_PHP教程

PHP内核研究:HASH表和变量_PHP教程

Jul 14, 2016 am 10:08 AM
hash php 핵심 변하기 쉬운 그리고 존재하다 재산 끊임없는 데이터 연구 친절한 표면

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内部的内存管理机制分配并处理内存。
 
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/477783.htmlTechArticlePHP HASH表 在PHP中,所有的数据 无论变量,常量,类,属性 都用Hash表来实现. 先要说说 HASH表 typedef struct bucket { ulong h; /* Used for numeric indexing */ ui...
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 Dec 20, 2024 am 11:31 AM

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

CakePHP 빠른 가이드 CakePHP 빠른 가이드 Sep 10, 2024 pm 05:27 PM

CakePHP는 오픈 소스 MVC 프레임워크입니다. 이를 통해 애플리케이션 개발, 배포 및 유지 관리가 훨씬 쉬워집니다. CakePHP에는 가장 일반적인 작업의 과부하를 줄이기 위한 여러 라이브러리가 있습니다.

PHP에서 HTML/XML을 어떻게 구문 분석하고 처리합니까? PHP에서 HTML/XML을 어떻게 구문 분석하고 처리합니까? Feb 07, 2025 am 11:57 AM

이 튜토리얼은 PHP를 사용하여 XML 문서를 효율적으로 처리하는 방법을 보여줍니다. XML (Extensible Markup Language)은 인간의 가독성과 기계 구문 분석을 위해 설계된 다목적 텍스트 기반 마크 업 언어입니다. 일반적으로 데이터 저장 AN에 사용됩니다

See all articles