美文网首页
PHP——1(PHP变量的存储结构)

PHP——1(PHP变量的存储结构)

作者: iscona | 来源:发表于2017-12-04 18:07 被阅读0次

PHP——2(PHP变量作用域)
PHP——3(PHP变量分离/引用(Variables Separation))
为辅助阅读,可直接跳过

首先声明,我并没有去读PHP的源码,只是对于php的有时候诡异的表现感兴趣,找了一下开发人员laruence的博客结合PHP提供的函数debug_zval_dump刺探得到了本博客所阐述的工作机理。

首先引用laruence关于PHP变量内部存储结构的部分内容(稍作修改)
在PHP中,所有的变量都是用一个结构-zval来保存的, 在Zend/zend.h中我们可以看到zval的定义:

 typedef struct _zval_struct {
        zvalue_value value;
        zend_uint refcount;
        zend_uchar type;
        zend_uchar is_ref;
  } zval;

其中zvalue_value是真正保存数据的关键部分,定义为一个联合体(union)

typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;

PHP中常见的变量类型有:

1. 整型/浮点/长整型/bool值 等等
2. 字符串
3. 数组/关联数组
4. 对象
5. 资源

PHP根据zval中的type字段来储存一个变量的真正类型,然后根据type来选择如何获取zvalue_value的值,比如对于整型和bool值:

    zval.type = IS_LONG;//整形
    zval.type = IS_BOOL;//布尔值

就去取zval.value.lval,对于bool值来说lval∈(0|1);如果是双精度,或者float则会去取zval.value的dval。而如果是字符串,那么:

zval.type = IS_STRING

这个时候,就会取:zval.value.str而这个也是个结构,存有C分格的字符串和字符串的长度。
而对于数组和对象,则type分别对应IS_ARRAY, IS_OBJECT, 相对应的则分别取zval.value.ht和obj
比较特别的是资源,在PHP中,资源是个很特别的变量,任何不属于PHP内建的变量类型的变量,都会被看作成资源来进行保存,比如,数据库句柄,打开的文件句柄等等。 对于资源:

type = IS_RESOURCE

这个时候,会去取zval.value.lval, 此时的lval是个整型的指示器, 然后PHP会再根据这个指示器在PHP内建的一个资源列表中查询相对应的资源,此时的lval就好像是对应于资源链表的偏移值。

ZEND_FETCH_RESOURCE(con, type, zval *, default, resource_name, resource_type);

借用这样的机制,PHP就实现了弱类型,因为对于ZE的来说,它所面对的永远都是同一种类型,那就是zval。


上面部分只是阐明了PHP变量的内部表示,要想知道内部表示是如何和用户脚本中的变量联系起来的,需要看laruence的另一篇博文深入理解PHP原理之变量作用域(Scope in PHP),同样引用部分内容(稍作修改)如下:
如果在脚本中写下:

<?php
  $var = "laruence";
  echo $var;
?>

ZE是如何把我的变量var和内部结构zval联系起来的呢?

PHP内部都是使用zval来表示变量的,但是对于上面的脚本,我们的变量是有名字的, var。而zval中并没有相应的字段来体现变量名。PHP内部一定有一个机制,来实现变量名到zval的映射。

在PHP中,所有的变量都会存储在一个数组中(确切的说是hash table)。

当你创建一个变量的时候,PHP会为这个变量分配一个zval,填入相应的变量值,然后将这个变量的名字,和指向这个zval的指针填入一个数组中。然后,当你获取这个变量的时候,PHP会通过查找这个数组,获得对应的zval。

查看_zend_executor_globals结构(这个结构在PHP的执行器保存一些执行相关的上下文信息)

struct _zend_executor_globals { 
     ....
    HashTable *active_symbol_table;/*活动符号表*/
    HashTable symbol_table;     /*全局符号表*/
 
    HashTable included_files;   
 
    jmp_buf *bailout;
    int error_reporting;
     .....
} 

对于以下程序:

<?php  
class class1  
{  
    public $member;  
      
    function __construct()  
    {  
        $this->member = 1;  
    }  
}  
  
$a = 1;  
$b = 0.56;  
$c = "string";  
$d = array(1=>1);  
$e = new class1;  
$f = tmpfile();  
  
debug_zval_dump($a);  
debug_zval_dump($b);  
debug_zval_dump($c);  
debug_zval_dump($d);  
debug_zval_dump($e);  
debug_zval_dump($f);  
?>  

该程序使用debug_zval_dump刺探LONG、DOUBLE、STRING、ARRAY、OBJECT、RESOURCE类型变量,结果如下

long(1) refcount(2)  
double(0.56) refcount(2)  
string(6) "string" refcount(2)  
array(1) refcount(2){  
  [1]=>  
  long(1) refcount(1)  
}  
object(class1)#1 (1) refcount(2){  
  ["member"]=>  
  long(1) refcount(1)  
}  
resource(4) of type (stream) refcount(2)  

分析绘制整个存储结构如下

image.png

对照此图就可以知道PHP各种类型的变量在内存中存储结构和用户变量如何跟内存结构挂钩

相关文章

  • PHP7 为什么变快了?

    PHP7比PHP5在性能上有很大的提升那么PHP7做了那些优化?变量存储优化 1.存储变量的结构体变小,结构体成员...

  • PHP——1(PHP变量的存储结构)

    PHP——2(PHP变量作用域)PHP——3(PHP变量分离/引用(Variables Separation))为...

  • PHP7和PHP5的区别以及特性

    PHP7相对于PHP5性能提升 1、变量存储字节减小,减少内存占用,提升变量操作速度 2、改善数组结构,数组元素和...

  • PHP知识梳理_GC

    参考PHP版本7.1 1.PHP 变量结构 2. Zend GC

  • 第一节

    1.变量 1.PHP 没有创建变量的命令。变量会在首次为其赋值时被创建:变量是存储信息的容器: PHP 变量规则:...

  • PHP gc机制

    在理解PHP垃圾回收机制(GC)之前,先了解一下变量的存储。php中变量存在于一个zval的变量容器中。结构如下:...

  • php简明手册

    # **PHP简明手册** ## **变量 和 常量** > 1. 变量和常量是PHP中最基本的数据存储单元,它们...

  • 3.PHP入门-语法概述(二)变量

    和其他语言一样,php使用变量来存储信息的"容器": 与代数类似 在 PHP 中,这些字母被称为变量。 PHP变量...

  • 2019-05-11 学习笔记(一)

    PHP变量 变量是存储信息的容器:实例: PHP 变量可用于保存值和表达。 变量规则: 变量以 $ 符号开头,其后...

  • php7变量实现_zval

    php5的变量实现 php通过一个zval结构体来实现变量,对于全局变量,php维护一个全局的hashtable,...

网友评论

      本文标题:PHP——1(PHP变量的存储结构)

      本文链接:https://www.haomeiwen.com/subject/izebhxtx.html