PHP-Kernel-Zval
这篇文章主要介绍的内容是关于PHP内核之zval,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
原文地址
作者:Twei 主页
前言
之前面试的时候面试官问过php中变量是如何实现的,遗憾的是只答道了大概是用结构体实现的。这篇文章是谷歌之后觉得总结 的比较到位的,故转载进而学习之。
正文
PHP中的数据类型
相对于 C、 C++、 Java等其他编程语言,PHP 是一个弱类型的语言,意味着当我们要使用一个变量时,不需要去声明它的类型。这个特性给我们带来了很多便利,同时有时也会带来一些陷阱。那么,PHP 是真的没有数据类型这个说法吗?
当然不是。在 PHP 官方文档中将 PHP 中的变量划分为三类:标量类型、复杂类型和特殊类型。标量类型包括布尔型(bool)、整型(int)、浮点型(float)和字符串(string);复杂类型包括数组(array)和对象(object);特殊类型包括 NULL 和资源(resource)。所以说 PHP 的变量细分的话,有 8 种数据类型。
总所周知,PHP 的底层是用 C 语言实现的。我们的 PHP 脚本会经过 Zend 引擎解析为 C 代码再执行。那么,一个 PHP 的变量,在 C 语言上是怎么表示的呢?它最终会被解析成什么样呢?
答案就是 zval。 不管什么类型的 PHP 变量,在 PHP 源代码中统一用一个叫做 zval 的结构表示。 zval 可以看做是 PHP 变量在 C 代码中的容器,它存储了这个变量的值、类型等相关信息。
那么我们就看一下 zval 的基本结构(需要一点 C 语言的基本知识)。
zval的基本结构
在 PHP 源代码中 zval 这个结构是一个名叫 _zval_struct
的结构体(struct),具体定义在源代码的 Zend/zend.h
文件中,下面是相关代码的摘录:
struct _zval_struct { zvalue_value value; /* value */ zend_uint refcount__gc; /* value of ref count */ zend_uchar type; /* active type */ zend_uchar is_ref__gc; /* if it is a ref variable */ }; typedef struct _zval_struct zval;
也就是说,在 PHP 的源码中,就用这一个结构体表示 PHP 中各种类型的变量,并且还可以实现其他的一些功能,例如垃圾回收(GC:Grabage Collection)。
可以看到它由 4 个字段构成,分别表示这个变量的某个信息。
ZVALUE_VALUE VALUE
value 用来表示变量的实际值,具体来说它是一个 zvalue_value 的联合体(union):
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { /* string */ char *val; int len; } str; HashTable *ht; /* hash table value,used for array */ zend_object_value obj; /* object */} zvalue_value;
可以看到 _zvalue_value 中只有 5 个字段,但是 PHP 中有 8 种数据类型,那么如何用 5 个字段表示 8 种类型呢?
这算是 PHP 设计比较巧妙的一个地方,它通过复用字段达到了减少字段的目的。例如,在 PHP 内部布尔型、整型及资源(只要存储资源的标识符即可)都是通过 lval 字段存储的;dval 用于存储浮点型;str 存储字符串;ht 存储数组(注意 PHP 中的数组其实是哈希表);而 obj 存储对象类型;如果所有字段全部置为 0 或 NULL则表示 PHP 中的 NULL,这样就达到了用 5 个字段存储 8 种类型的值。
ZEND_UINT REFCOUNT__GC
从它的后缀 gc 可以看到,这个字段是和垃圾回收相关的。
它实际上是一个计数器,用来保存有多少变量指向该zval。在变量生成时,置为1,也就是 refcount = 1。
对变量进行不同的操作会改变它的值。典型的赋值操作如
b 会使 refcount 加 1,而 unset() 操作会相应的减 1。
通过判断它的值可以进行垃圾回收。在 PHP5.3 之前,使用引用计数的机制来实现 GC:如果一个 zval 的 refcount 减为 0,那么 Zend 引擎会认为没有任何变量指向该 zval,就会释放该 zval 所占的内存空间。但仅仅使用引用计数机制无法释放掉循环引用的 zval,这是就会导致内存泄露(Memory Leak)。
在 5.3 以前,这个字段的名字还叫做 refcount,5.3 以后,在引入新的垃圾回收算法来对付循环引用,作者加入了大量的宏来操作 refcount,为了能让错误更快的显现,所以改名为 refcount__gc, 迫使大家都使用宏来操作 refcount。
类似的, 还有第四个字段 is_ref, 这个值表示了 PHP 中的一个类型是否是引用。
想了解 PHP 的垃圾回收机制,可以参考这篇博客:PHP的垃圾回收机制
注:变量,也可以被称为符号,symbol。所有的符号都存在符号表(symbol table)中, 不同的作用域使用不同的符号表,关于这一点,这篇博客进行了讲解。
ZEND_UCHAR TYPE
这个字段用于表明变量属于 PHP 8 种类型的哪种。在 zend 内部,这些类型对应于下面的宏(代码位置 phpsrc/Zend/zend.h):
#define IS_NULL 0#define IS_LONG 1#define IS_DOUBLE 2#define IS_BOOL 3#define IS_ARRAY 4#define IS_OBJECT 5#define IS_STRING 6#define IS_RESOURCE 7#define IS_CONSTANT 8#define IS_CONSTANT_ARRAY 9#define IS_CALLABLE 10
ZEND_UCHAR IS_REF__GC
这个字段用于标记变量是否是引用变量。对于普通的变量,该值为 0,而对于引用型的变量,该值为 1。这个变量会影响 zval 的共享、分离等。它也和 PHP 的垃圾回收有关。
PHP7中的zval
上述的 zval 结构,随着时间的发展,暴露出许多问题,例如占用空间大(24 字节)、不支持拓展、 对象和引用效率差等,所以在 PHP7 的时候,对 zval 进行了较大的改变,现在它的结构是这样的:
struct _zval_struct { union { zend_long lval; /* long value */ double dval; /* double value */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } value; union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar type, /* active type */ zend_uchar type_flags, zend_uchar const_flags, zend_uchar reserved) /* call info for EX(This) */ } v; uint32_t type_info; } u1; union { uint32_t var_flags; uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ } u2; };
虽然看起来变得好大,但其实仔细看,它的字段都是联合体,这个新的 zval 在 64 位环境下,只需要 16 个字节(2 个指针 size)。PHP7 中的 zval,已经变成了一个值指针,它要么保存着原始值,要么保存着指向一个保存原始值的指针。
这部分内容来自鸟哥的GitHub。
总结
zval 是一种 C 语言实现的数据结构,功能是作为 PHP 变量的容器;
它保存了变量的各种信息(如类型和值),并为其他功能(如垃圾回收)提供支持;
在不同的 PHP 版本中,它的结构不同。PHP7 的 zval 占 16 个字节,PHP5 的要占 24 个字节。
参考
PHP内核探索之变量(1)变量的容器-Zval
PHP垃圾回收深入理解
深入理解PHP7之zval
相关推荐:
Das obige ist der detaillierte Inhalt vonPHP-Kernel-Zval. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



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.

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

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

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

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

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 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.

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
