Jadual Kandungan
前言
正文
ZVALUE_VALUE VALUE
ZEND_UINT REFCOUNT__GC
ZEND_UCHAR TYPE
ZEND_UCHAR IS_REF__GC
PHP7中的zval
总结
参考

PHP内核之zval

Apr 19, 2018 am 09:26 AM
php zval Inti

这篇文章主要介绍的内容是关于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;
Salin selepas log masuk

也就是说,在 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;
Salin selepas log masuk

可以看到 _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
Salin selepas log masuk

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;
};
Salin selepas log masuk

虽然看起来变得好大,但其实仔细看,它的字段都是联合体,这个新的 zval 在 64 位环境下,只需要 16 个字节(2 个指针 size)。PHP7 中的 zval,已经变成了一个值指针,它要么保存着原始值,要么保存着指向一个保存原始值的指针。

这部分内容来自鸟哥的GitHub。

总结


  1. zval 是一种 C 语言实现的数据结构,功能是作为 PHP 变量的容器;

  2. 它保存了变量的各种信息(如类型和值),并为其他功能(如垃圾回收)提供支持;

  3. 在不同的 PHP 版本中,它的结构不同。PHP7 的 zval 占 16 个字节,PHP5 的要占 24 个字节。

参考


PHP内核探索之变量(1)变量的容器-Zval
PHP垃圾回收深入理解
深入理解PHP7之zval

相关推荐:

PHP内核之探究内存管理与缓存机制

PHP内核分析-Zend虚拟机详解

Atas ialah kandungan terperinci PHP内核之zval. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Panduan Pemasangan dan Naik Taraf PHP 8.4 untuk Ubuntu dan Debian Panduan Pemasangan dan Naik Taraf PHP 8.4 untuk Ubuntu dan Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 membawa beberapa ciri baharu, peningkatan keselamatan dan peningkatan prestasi dengan jumlah penamatan dan penyingkiran ciri yang sihat. Panduan ini menerangkan cara memasang PHP 8.4 atau naik taraf kepada PHP 8.4 pada Ubuntu, Debian, atau terbitan mereka

Tarikh dan Masa CakePHP Tarikh dan Masa CakePHP Sep 10, 2024 pm 05:27 PM

Untuk bekerja dengan tarikh dan masa dalam cakephp4, kami akan menggunakan kelas FrozenTime yang tersedia.

Bincangkan CakePHP Bincangkan CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP ialah rangka kerja sumber terbuka untuk PHP. Ia bertujuan untuk menjadikan pembangunan, penggunaan dan penyelenggaraan aplikasi lebih mudah. CakePHP adalah berdasarkan seni bina seperti MVC yang berkuasa dan mudah difahami. Model, Pandangan dan Pengawal gu

Muat naik Fail CakePHP Muat naik Fail CakePHP Sep 10, 2024 pm 05:27 PM

Untuk mengusahakan muat naik fail, kami akan menggunakan pembantu borang. Di sini, adalah contoh untuk muat naik fail.

Pengesah Mencipta CakePHP Pengesah Mencipta CakePHP Sep 10, 2024 pm 05:26 PM

Pengesah boleh dibuat dengan menambah dua baris berikut dalam pengawal.

Cara Menyediakan Kod Visual Studio (Kod VS) untuk Pembangunan PHP Cara Menyediakan Kod Visual Studio (Kod VS) untuk Pembangunan PHP Dec 20, 2024 am 11:31 AM

Kod Visual Studio, juga dikenali sebagai Kod VS, ialah editor kod sumber percuma — atau persekitaran pembangunan bersepadu (IDE) — tersedia untuk semua sistem pengendalian utama. Dengan koleksi sambungan yang besar untuk banyak bahasa pengaturcaraan, Kod VS boleh menjadi c

Panduan Ringkas CakePHP Panduan Ringkas CakePHP Sep 10, 2024 pm 05:27 PM

CakePHP ialah rangka kerja MVC sumber terbuka. Ia menjadikan pembangunan, penggunaan dan penyelenggaraan aplikasi lebih mudah. CakePHP mempunyai beberapa perpustakaan untuk mengurangkan beban tugas yang paling biasa.

Bagaimana anda menghuraikan dan memproses HTML/XML dalam PHP? Bagaimana anda menghuraikan dan memproses HTML/XML dalam PHP? Feb 07, 2025 am 11:57 AM

Tutorial ini menunjukkan cara memproses dokumen XML dengan cekap menggunakan PHP. XML (bahasa markup extensible) adalah bahasa markup berasaskan teks yang serba boleh yang direka untuk pembacaan manusia dan parsing mesin. Ia biasanya digunakan untuk penyimpanan data

See all articles