php变量是一个zval结构体,包含引用计数、活动类型、是否为引用、和zvalue_value的结构体。zvalue_value是一个联合结构,包括长整数long、浮点数double、字符串、数组哈希表HashTable、和对象值结构zend_object_value。其中ht为数组,obj为对象,resource使用lval为句柄。
typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;
struct _zval_struct {
zvalue_value value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
};
typedef struct _zval_struct zval;
HashTable哈希表是包含一组哈希表结构和函数,其最大的为0x80000000,bucket是指针链接表,arKey为Key,pData为数据的指针,hashtable为主表,arBuckets为bucket指针数组,结构如下:
typedef struct bucket {
ulong h;
uint nKeyLength;
void *pData;
void *pDataPtr;
struct bucket *pListNext;
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
char arKey[1];
} Bucket;
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer;
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;
} HashTable;
php对象值结构zend_object_value是一个包含对象句柄zend_object_handle、zend_object_handlers的指针,zend_object_handlers包含一组操作对象的函数,如引用计数(add_ref、del_ref)和其它函数(clone_obj、read_property、write_property、has_property、unset_property、get_properties、get_method、call_method、get_constructor、cast_object、get_class_name、count_elements等)。对象句柄zend_object_handle是objects_store中对象存储池store bulk的索引。
php对象zend_object包括类结构,和一个属性properties的哈希表。类结构zend_class_entry包括类型,名称,父类指针,引用计数,文件名,模块结构指针,(方法、属性默认值、属性信息、默认静态成员、静态成员、常量、函数)的哈希表,和一组系统方法(construct、destructor、clone、__get、__set、__unset、__isset、__call、__tostring、serialize_func、unserialize_func),以及接口结构。类析构当引用计数等于0,将释放属性默认值、属性信息,常量、函数等的哈希表和接口结构。
typedef struct _zend_object_value {
zend_object_handle handle;
zend_object_handlers *handlers;
} zend_object_value;
typedef struct _zend_object {
zend_class_entry *ce;
HashTable *properties;
} zend_object;
struct _zend_class_entry {
char type;
char *name;
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
HashTable function_table;
HashTable default_properties;
HashTable properties_info;
HashTable default_static_members;
HashTable *static_members;
HashTable constants_table;
struct _zend_function_entry *builtin_functions;
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
union _zend_function *__get;
union _zend_function *__set;
union _zend_function *__unset;
union _zend_function *__isset;
union _zend_function *__call;
union _zend_function *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
zend_class_entry **interfaces;
zend_uint num_interfaces;
char *filename;
zend_uint line_start;
zend_uint line_end;
char *doc_comment;
zend_uint doc_comment_len;
struct _zend_module_entry *module;
};
typedef struct _zend_property_info {
zend_uint flags;
char *name;
int name_length;
ulong h;
char *doc_comment;
int doc_comment_len;
zend_class_entry *ce;
} zend_property_info;
资源resource使用zval中lval为句柄,资源存储在全局变量HashTable regular_list,持久资源存储在全局变量persistent_list,资源句柄是regular_list的索引index,资源使用zend_rsrc_list_entry结构存储,如果引用计数refcount等于0,将资源存储列表regular_list、persistent_list对应的资源zend_rsrc_list_entry删除,同时释放资源。释放资源时,找到对应的析构方法,释放对应的内容,持久资源使用其持久资源对应的析构方法。资源模块一般带有资源和持久资源两种析构方法。
typedef struct _zend_rsrc_list_entry {
void *ptr;
int type;
int refcount;
} zend_rsrc_list_entry;
常量存储在全局变量HashTable *zend_constants,常量以zend_constant结构注册到zend_constants中,注册常量时常量名称将转换为小写,故php常量大小写不敏感。查找常量时,首先查找类常量,即classname::constname,如果有效将查找类的常量表,否则查找全局变量zend_constants哈希表的内容。系统设定的常量除错误类型常量外,还有TRUE,FALSE,NULL,ZEND_THREAD_SAFE。
typedef struct _zend_constant {
zval value;
int flags;
char *name;
uint name_len;
int module_number;
} zend_constant;
Php内置函数包括:zend_version,func_num_args,func_get_arg,func_get_args,strlen,strcmp,strncmp,strcasecmp,strncasecmp,each,error_reporting,define,defined,get_class,get_parent_class,method_exists,property_exists,class_exists,interface_exists,function_exists,get_included_files,is_subclass_of,is_a,get_class_vars,get_object_vars,get_class_methods,trigger_error,set_error_handler,restore_error_handler,set_exception_handler,restore_exception_handler,get_declared_classes,get_declared_interfaces,get_defined_functions,get_defined_vars ,get_loaded_extensions ,extension_loaded,get_resource_type ,get_extension_funcs,get_defined_constants,create_function。
函数参数获取通过参数栈顶部得到,函数注册在全局变量function_table中,一般类方法或者类静态方法,首先在类中,然后在父类中查找,在全局函数表中查找,检查方法是否可用(如是否为抽象方法、过时方法),将参数压入参数栈,设置符号表和范围,设置返回值和中间代码,执行代码,如果是内部函数,直接调用。
typedef struct _zend_function_entry {
char *fname;
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
struct _zend_arg_info *arg_info;
zend_uint num_args;
zend_uint flags;
} zend_function_entry;
typedef struct _zend_arg_info {
char *name;
zend_uint name_len;
char *class_name;
zend_uint class_name_len;
zend_bool array_type_hint;
zend_bool allow_null;
zend_bool pass_by_reference;
zend_bool return_reference;
int required_num_args;
} zend_arg_info;
typedef struct _zend_fcall_info {
size_t size;
HashTable *function_table;
zval *function_name;
HashTable *symbol_table;
zval **retval_ptr_ptr;
zend_uint param_count;
zval ***params;
zval **object_pp;
zend_bool no_separation;
} zend_fcall_info;
Php使用自己的内存管理代码,使用的内存在php全局堆heap中分配,当前内存不够时,发布内存不够安全错误,内存以块形式存在,可设置内存相关环境变量ZEND_MM_SEG_SIZE和ZEND_MM_COMPACT,先搜索最大内存块,分配内存,否则查找合适的BUCKET,如果没有合适内存块,扩大内存段,如果内存超限,发布内存不够安全错误。释放内存时,将内存块加入free内存链接池,并进行内存块归并。可以检查内存全局堆是否有泄漏。
struct _zend_mm_heap {
int use_zend_alloc;
size_t free_bitmap;
size_t large_free_bitmap;
size_t block_size;
size_t compact_size;
zend_mm_segment *segments_list;
zend_mm_storage *storage;
size_t real_size;
size_t real_peak;
size_t limit;
size_t size;
size_t peak;
size_t reserve_size;
void *reserve;
int overflow;
int internal;
zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2];
zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS];
zend_mm_free_block *rest_buckets[2];
};
接受apche的请求,request初始化,初始化输出缓冲,找到入口文件,
初始化执行环境,
编译文件,
运行编译结果,可在zend虚拟机中运行。
释放执行环境。
Flex 词法分析,Bison 语法分析。
开启内存管理,
开启扩展模块机制,
设置辅助函数,
初始化error表,
初始化栈帧stock frame,
初始化符号cache表、函数表、类表,
置入参数栈,
初始化符号表,
初始化全局变量GLOBALS,
初始化模块列表,
初始化包含文件表include files,
初始化对象池,
初始化持久资源列表,
初始化全局常量,
设置内部函数,
初始化ticks_count,用户错误处理句柄,异常exception,超时timed_out,等。
关闭超时函数,
释放持久资源列表,
释放全局常量,
模块列表模块消活deactive,
符号表symbol_table析构,
取消用户错误处理句柄、用户错误处理句柄,
清除函数、类的静态变量、参数栈、操作数组、符号cache表,
对象池析构,
释放资源列表,
清除包含文件表include files,
清除栈帧stock frame。
如果设置运行超时,
Windows版本启动超时创建线程,创建线程创建超时窗口、事件处理函数,设置定时器。可以设置新的定时器Timer,或者取消定时器。
其它系统直接设置定时器。可以设置新的定时,或者取消定时。
to int:NULL->0,double->int,string->int,array->不空1 or 0,bool->true 1 or 0,resource->句柄值,object->如可转换,转换,or如兼容,不空1 or 0,default->0。
to double:NULL->0.0,其它如上。
to null:object->如果可转换,转换。其它,释放变量,设置类型为NULL。
to boolean:null->false,其它转换为int的值不为0,true;or false。
to string:null->空字符串,int、double->相应的字符串,bool->true,为“1”,or空字符串,resource->“Resource id [句柄数字]”; array-> "Array",;object->如可转换,转换__tostring,or "Object"。
to array:NULL->空数组;object->属性property转换为数组;其它,成为数组的第一个成员。
to object::NULL->空对象;array->数值值转换为property;其它,成为对象的一个名为scalar成员。