现在的位置: 主页 > 公司荣誉 > 文章列表

PHP内核探索之变量(1)Zval

作者:昆明飞华工贸有限公司 来源:www.kmfhgm.com    未知发布时间:2017-09-04 13:25:56
PHP内核探索之变量(1)Zval 作为数据的容器,我们常常需要跟变量打交道,不管这个变量是数字、数组、字符串、对象还是其他,因而可以说变量是构成语言的不可或缺的基础。本文是PHP内核探索之变量的第一篇,主要介绍zval的基本知识,包括如下几个方面的内容:

Zval的基本结构

查看zval的方法:debug_zval_dump和xdebug

Zval的原理,COW等

由于写作仓促,难免会有错误,欢迎指出。

一、Zval的基本结构

Zval是PHP中最重要的数据结构之一(另一个比较重要的数据结构是hash table),它包含了PHP中的变量值和类型的相关信息。它是一个struct,基本结构为:

struct _zval_struct {

zvalue_value value; /* value */

zend_uint refcount__gc; /* variable ref count */

zend_uchar type; /* active type */

zend_uchar is_ref__gc; /* if it is a ref variable */

};

typedef struct _zval_struct zval;

其中:

1.  zval_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;

2.  zend_uint refcount__gc

该值实际上是一个计数器,用来保存有多少变量(或者符号,symbols,所有的符号都存在符号表(symble table)中, 不同的作用域使用不同的符号表,关于这一点,我们之后会论述)指向该zval。在变量生成时,其refcount=1,典型的赋值操作如$a = $b会令zval的refcount加1,而unset操作会相应的减1。在PHP5.3之前,使用引用计数的机制来实现GC,如果一个zval的refcount较少到0,那么Zend引擎会认为没有任何变量指向该zval,因此会释放该zval所占的内存空间。但,事情有时并不会那么简单。后面我们会看到,单纯的引用计数机制无法GC掉循环引用的zval,即使指向该zval的变量已经被unset,从而导致了内存泄露(Memory Leak)。

3.  zend_uchar type

该字段用于表明变量的实际类型。在开始学习PHP的时候,我们已经知道,PHP中的变量包括四种标量类型(bool,int,float,string),两种复合类型(array, object)和两种特殊的类型(resource 和NULL)。在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

4.  is_ref__gc

这个字段用于标记变量是否是引用变量。对于普通的变量,该值为0,而对于引用型的变量,该值为1。这个变量会影响zval的共享、分离等。关于这点,我们之后会有论述。

正如名字所示,ref_count__gc和is_ref__gc是PHP的GC机制所需的很重要的两个字段,这两个字段的值,可以通过xdebug等调试工具查看。

二、xdebug的安装配置

Xdebug是一个开源的PHP 性能分析和debug工具。虽然对于一般的程序调试,var_dump,echo,print,debug_backtrace等常见的调试工具已经基本够用,但对于一些复杂的调试和性能测试,xdebug绝对是一个很好的帮手(其他的如Xhprof等工具也很优秀)。

本文的基本环境:

安装Xdebug的基本过程为(实际上是源码编译一个扩展):

1.  下载源码包.

  下载地址为:http://www.xdebug.org/docs/install

  本文中下载的版本为:Xdebug-2.6.tar.gz

2.  解压

tar xvzf xdebug-2.6.tar.gz

3.  在xdebug的目录执行phpize

4.  ./configure 配置

5.  Make&& make install

这会生成xdebug.so扩展文件(zend_extension),位置在xdebug/modules

6.  在php.ini中加载xdebug扩展

zend_extension=your-xdebug-path/xdebug.so

7.  添加xdebug的配置

xdebug.profiler_enable = on

xdebug.default_enable = on

xdebug.trace_output_dir="/tmp/xdebug"

xdebug.trace_output_name = trace.%c.%p

xdebug.profiler_output_dir="/tmp/xdebug"

xdebug.profiler_output_name="cachegrind.out.%s"

这里不再详细介绍各个配置项的含义,详细的请看:http://www.xdebug.org/docs/all

现在,PHP中,应该已经有了Xdebug的扩展信息(php –m,也可以phpinfo()):

在Xdebug中,可以通过xdebug_debug_zval打印Zval的信息:

<?php

$a = array( 'test' );

$a[] = &$a;

xdebug_debug_zval( 'a' );

3.  Zval的更多原理

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:宜昌网站制作 http://yichang.666rj.com

上一篇:为什么始终如一致力香港服务器租用 下一篇:最后一页