博客
关于我
PHP内核介绍及扩展开发指南—基础知识
阅读量:793 次
发布时间:2023-03-01

本文共 2386 字,大约阅读时间需要 7 分钟。

Zend引擎内部机制解析

1. 基础知识

本章将简要介绍Zend引擎的内部机制,这些知识与Extensions密切相关,同时也能帮助我们编写更加高效的PHP代码。

1.1 PHP变量的存储

PHP变量的存储在Zend引擎中采用了一种特殊的数据结构——zval(zvalue,值结构),用于存储PHP变量的值。这种结构不仅支持多种数据类型,还能实现变量的复用和引用。

1.1.1 zval结构

zval结构由以下几个部分组成:

  • long lval:用于存储long类型的值,通常用于整数。
  • double dval:用于存储double类型的值,通常用于浮点数。
  • char *valint len:用于存储字符串类型的值,val指向字符串的字符数组,len表示字符串的长度。
  • *HashTable ht:用于存储关联数组的键值对。
  • zend_object_value obj:用于存储对象类型的值。

此外,zval结构还包含以下两个成员用于管理引用关系:

  • zend_uint refcount:表示当前zval的引用计数。
  • zend_uchar is_ref:表示当前zval是否处于引用状态。

1.1.2 引用计数

引用计数机制在垃圾回收、内存管理以及字符串处理等方面发挥着重要作用。Zend引擎通过引用计数实现多个变量共享同一份zval的功能。当多个变量共享一个zval时,修改其中一个变量会自动影响其他变量。这个过程通过refcountis_ref两个成员来实现。

  • refcount用于记录当前zval被引用的次数。当refcount减少到0时,Zend会回收该zval。
  • is_ref用于标记当前zval是否处于引用状态。当is_ref为0时,表示该zval采用的是非引用赋值机制;当is_ref为1时,表示该zval采用的是引用赋值机制。

1.1.3 zval状态切换

在实际应用中,变量的赋值方式可能会混合使用引用和非引用,这会导致zval的状态切换。例如:

$a = 1;
$b = $a;
$c = $b;
$d = $c; // 向一个引用型变量赋值

在上述代码中,$a、$b、$c都是引用型变量,$d是一个非引用型变量。由于$d的引用会导致zval的复制,$d独立于其他变量。

1.1.4 参数传递

PHP函数参数的传递与变量赋值方式一致。非引用传递相当于非引用赋值,引用传递相当于引用赋值。引用传递可能导致zval状态的切换。

1.2 HashTable结构

HashTable(哈希表)是Zend引擎中最重要和最常用的数据结构,几乎用于存储所有类型的数据。其核心结构定义如下:

typedef struct _hashtable {
uint nTableSize; // 表格的大小
uint nTableMask; // 表格掩码
uint nNumOfElements; // 元素数量
ulong nNextFreeElement; // 下一个空闲元素的位置
Bucket *pListHead; // 表格的双链表头
Bucket *pListTail; // 表格的双链表尾
Bucket **arBuckets; // 表格的哈希数组
destructor_func_t pDestructor; // 销毁回调函数
zend_bool persistent; // 是否使用C的内存分配
unsigned char nApplyCount; // 应用次数
zend_bool bApplyProtection; // 是否需要保护
#if ZEND_DEBUG
int inconsistent; // 不一致性标志
#endif
} Hashtable;

HashTable的实现细节

  • 链表散列:HashTable采用链表散列结合双链表的方式实现快速查找和遍历。
  • nTableMask:用于将哈希值转换为索引,确保索引在有效范围内。
  • pDataPtr:用于存储哈希表中的值,通常用于优化内存分配。
  • arKey的大小:为了减少内存分配次数,arKey的大小固定为1,并通过cookie技术存储更多信息。
  • 1.2.1 PHP数组

    PHP数组实际上是基于HashTable实现的关联数组。其核心特点包括:

    • 动态数组:支持动态扩展和灵活定义。
    • 多种存储类型:支持整数、字符串、浮点数、对象、资源等多种数据类型。
    • 混合操作:支持关联数组和非关联数组的混合使用。

    1.2.2 变量符号表

    除了存储PHP数组,HashTable还被广泛用于存储变量符号信息。例如,symbol_tableactive_symbol_table用于存储全局和局部变量符号信息。这种机制支持函数局部变量的作用域控制。

    1.3 内存和文件

    在PHP程序中,内存和文件资源的管理至关重要。为了避免内存泄漏,Zend引擎提供了一套内存分配API,基于页面自动回收内存。这些API应在模块代码中使用,以确保内存的安全释放。

    1.3.1 内存管理函数

    • emalloc():分配内存。
    • efree():释放内存。
    • estrndup():分配带有cookie的内存。
    • ecalloc():分配带有初始化值的内存。
    • erealloc():调整已有内存块的大小。

    通过使用Zend提供的内存管理函数,可以确保内存的安全分配和释放。

    1.3.2 文件操作

    除了内存管理,Zend还提供了一系列文件操作API。这些API基于虚拟目录机制,确保文件操作始终在指定目录内执行,避免文件泄漏问题。


    本文首发于:百度技术博客

    如需转载请联系原作者。

    你可能感兴趣的文章