php从内存中获取源码_PHP源码分析之变量的存储过程分解

PHP代码如下:

$php_var = 1;

对应C的代码是:

zval* c_var;    //定义PHP变量指针

MAKE_STD_ZVAL(c_var);  //初始化PHP变量

ZVAL_LONG(c_var,1) ;//赋值

ZEND_SET_SYMBL( EG(active_symbol_table), " php_var ", c_var);//注册到全局变量符号表

一.首先看第一行: zval* c_var;//申明一个zval指针c_var; zval的结构如下:

struct _zval_struct {

/* Variable information */

zvalue_value value;     /* 变量的值 */

zend_uint refcount;     /* 引用计数,垃圾回收的时候用到 */

zend_uchar type;        /* 变量类型 */

zend_uchar is_ref;      /* 是否为引用变量 */

};

typedef struct _zval_struct zval;

其中值zvalue_value的结构如下:

typedef union _zvalue_value {

long lval;              /* 长整形*/

double dval;            /* 双精度类型 */

struct {                  /* 字符串类型的值 */

char *val;

int len;

} str;

HashTable *ht;              /* 数组类型的值 */

zend_object_value obj;     /*对象类型的值*/

} zvalue_value;

二.接下来看第二行: MAKE_STD_ZVAL(new_val);//变量初始化 相关宏如下: //初始化

#define MAKE_STD_ZVAL(zv)                \

ALLOC_ZVAL(zv); \

INIT_PZVAL(zv);

#define ALLOC_ZVAL(z)   \

ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)

#define ZEND_FAST_ALLOC(p, type, fc_type)   \

(p) = (type *) emalloc(sizeof(type))

#define INIT_PZVAL(z)       \

(z)->refcount = 1;      \

(z)->is_ref = 0;

展开后为:

(c_var) = (zval *) emalloc(sizeof(zval));  //分配内存

(c_var)-> refcount = 1;  //引用计数初始化

(c_var)-> is_ref = 0; //是否引用

可以看到其作用就是分配内存,初始化refcount,is_ref

三.下面看第三行 ZVAL_LONG(c_var,1) 相关宏为:

//定义值

#define ZVAL_LONG(z, l) {           \

Z_TYPE_P(z) = IS_LONG;      \

Z_LVAL_P(z) = l;            \

}

#define Z_TYPE_P(zval_p)    Z_TYPE(*zval_p)

#define Z_TYPE(zval)        (zval).type

#define Z_LVAL_P(zval_p)    Z_LVAL(*zval_p)

#define Z_LVAL(zval)            (zval).value.lval

展开后为:

(* c_var).type = IS_LONG;

(* c_var).value = 1;

四:接下来看第四行: ZEND_SET_SYMBOL( EG(active_symbol_table), “php_var”, c_var); 首先说明下PHP的变量是存在一个hashtable里的

struct _zend_executor_globals {

….

HashTable symbol_table;//全局变量的符号表

HashTable *active_symbol_table;//局部变量的符号表

…..

};

Hashtable的Key为变量的名称,即php_var,值为指向PHP变量的指针,即c_var指针; 相关宏为:

#define ZEND_SET_SYMBOL(symtable, name, var)          \   {                                                     \

char *_name = (name);                         \

ZEND_SET_SYMBOL_WITH_LENGTH(symtable, _name, strlen(_name)+1, var, 1, 0);   \

}

//主要的实现为下面这个函数:

#define ZEND_SET_SYMBOL_WITH_LENGTH(symtable, name, name_length, var, _refcount, _is_ref)                                                       \

{

zval **orig_var;                                        \

if (zend_hash_find(symtable, (name), (name_length), (void **) &orig_var)==SUCCESS                                                         \

&& PZVAL_IS_REF(*orig_var)) {                     \

(var)->refcount = (*orig_var)->refcount;                  \

(var)->is_ref = 1;                                \

if (_refcount) {                                      \

(var)->refcount += _refcount-1;               \

}                                             \

zval_dtor(*orig_var);                             \

**orig_var = *(var);                                  \

FREE_ZVAL(var);                               \

} else {                                              \

(var)->is_ref = _is_ref;                              \

if (_refcount) {                                      \

(var)->refcount = _refcount;                      \

}                                             \

zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL);                                                           \

}                                                  \

}

该函数的功能是:

1. 如果全局符号表已经存在该变量且是引用类型,则

a. 将原来变量的引用计数refcount,is_ref信息赋给c_var;

b. 释放掉原来变量zvalue的值,比如原来其值指向的是一个mysql连接资源,则释放该资源。

c. 将c_var指向的变量赋值给原来的变量 d. 释放c_var的内存空间 这样保证了,如果变量被应用,值一起改变。比如如果前面有$b=&a;

2. 如果全局符号表不存在该变量或者存在该变量但不是引用变量,则直接改变其值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/528054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php有哪些高级扩展,php扩展有哪些

什么是PHP扩展?为PHP提供一些扩展的功能常见的PHP扩展mysql-----提供给PHP操作MySQL数据库的功能gd2----动态创建图像xdebug-----跟踪、调试和分析PHP程序的运行状况查看PHP扩展1.使用phpinfo探针phpinfo()---输出关于PHP配置的信息输出PHP当前状态的大量信息&#…

php pdo 绕过,php-带PDO的忘记密码脚本(需要解密)

我可能有一个愚蠢的愚蠢的问题……我正在做一个被遗忘的密码脚本(当然是登录系统),但是我被卡住了.我创建了一个具有特殊ID的代码(有效,是的!),但是我无法对其进行解密…您能帮我吗?这是我创建特殊ID的功能:Recovery_Script.phpinclude "…

php 图片系统,Linger

软件简介Linger 是 PHP 图片分享系统。一个精简的图片分享系统网站,采用Bootstrap前端框架,支持部分页面的移动端自适应。同时采用HTML5进行图片批量上传。使用了一个简单的时间线动态展示,可作为简易的图片社交社区。有一个完整的用户中心和…

php 传递类名,php 对象和数组序列化 serialize()返回字符串方便存储和传递 unserialize()反序列化 不丢失类型和结构...

现在开发中经常使用序列号和反序列化技术手段,php开发中也大量使用到。如下几个知名系统都使用了大量的序列化技术ecshop2. phpcms内容管理系统3.laravel框架一、序列号的目的?方便数组和对象的传输或存储,同时不丢失其类型和结构如下是ecsho…

基本的排序算法php,php四种基础排序算法

原标题:php四种基础排序算法曾经有网友问我关于面试题的问题,今天就发一个面试题笔试经常会出的排序算法,大家可以参考一下,如有问题可以给我留言。/*** php四种基础排序算法的运行时间比较* authors Jesse (jesse152163.com)* da…

php io流 读取wav,记php中的io流---帮助理解

//注意:当读到文件末尾的时候会返回-1.正常情况下是不会返回-1的。public static void main(String[] args) throws IOException {File fnew File("aaa.txt"); //定位文件位置InputStream innew FileInputStream(f); //创建字节输入流连接到文件byte[] bn…

php获取jsp的session的值,在JSP或Servlet中获取session数量

enumsul.getUserList();int i0;while(enums.hasMoreElements()){out.println(enums.nextElement());out.println(" ");if(i10){out.println("");}}out.println("当前在线的用户数:"i);out.println("退出登录");out.clos…

php如何查看上传的文件大小,PHP设置最大上传文件大小

一、修改php.ini文件。找到php中的php.ini文件,用写字板打开:1、查找post_max_size,指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值,默认为8M,看你自己需要进行改变。2、查找File Uploads&…

java xy,java – 某个z深度的xy位置

我强烈建议你研究一些线性代数或矩阵数学用于3d图形.它既有趣又简单,但比SO答案要长一点.我会尝试:)免责声明:我不知道你正在使用的API!看起来你正在为一个位置返回3个坐标(通常称为顶点).但是你也提到了一个投影矩阵,该函数有4个坐标.通常,着色器或API将…

django mysql 游标,MySQL Cursor 存储过程之游标与相关循环

简单介绍游标在检索出来的行中,前进或者后退一行或多行,就需要用到所谓的“游标”。游标不是某个SELECT语句,但是它是被该语句检索出来的结果集。几个特点:MySQL游标只能用于存储过程(和函数)。游标是不能滚动的,也就是…

java 8 optional 类,Java8新特性-Optional类

Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。常用方法:Optional.of(T t) : 创建一个 Optional 实例Opt…

java 进度条jsp,jsp进度条_jsp技巧

开始页面:start.jsp状态页面:status.jspJSP进度条setTimeout(“locationstatus.jsp”, 1000);JSP进度条结果: %CELLPADDING0 CELLSPACING2> percent; i - 10) { %> 正在执行完成尚未开始已停止停止页面:stop.jsp业务逻辑bean:TaskBean.javapackage progress;import java.…

覆盖php配置文件,配置 – 用另一个文件覆盖php-fpm池配置值

必须自定义新服务器的php-fpm池配置,我想知道是否有可能/允许/建议有一个新的池文件,该名称在原始文件之后按字母顺序排列,其中只有值覆盖初始配置.原始配置位于/etc/php/7.0/fpm/pool.d,名为www.conf.看来,根据与安装相关的页面,工程师直接修改原件(保存初始值的副本).例如.[w…

子主题function php,php – 带有依赖项的子主题

我正在尝试创建一个儿童主题.父主题有一个style.css和all,我正在查看wp_enqueue_style()函数,它说你可以包含依赖项.这意味着主题自己的style.css可以是活动的,而在我的子主题中,如果我在style.css中指定相同的规则,它应该覆盖它.但依赖是一个句柄数组.我如何找到这些手柄&…

matlab节点导纳阵求逆,关于利用矩阵稀疏技术求解节点导纳矩阵的MATLAB编程

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼求大神帮忙看看这个程序,解释一下!%形成节点导纳矩阵%考虑参考节点%考虑互感支路function [d_g,d_b,u_g,u_b]calyy(itoi,noels_hgln,noelsnum_hgln,bs_noels,bs_cp,gb_hgln,gb_noels,gb_cp,lv_bs,lv_hgln,lv…

mysql还原txt表的字段结构,mysql 修改表结构(转)

1.增加一个字段(一列)alter table table_name add column column_name type default value; type指该字段的类型,value指该字段的默认值例如:alter table mybook add column publish_house varchar(10) default ;2.更改一个字段名字(也可以改变类型和默认值)alter table tabl…

python操作json字符串,超详细的Python文件操作知识

来自:CSDN,作者:南枝向暖北枝寒MA链接:https://blog.csdn.net/mall_lucy/article/details/104547365【导语】:python进行文件操作,在日常编程中是很常用的。为了方便大家,这里对各种文件操作的知…

php头尾分离,laravel怎么做模板的头尾分离

关注博主,每天分享项目实战经验1.首先找到页面的公共部分,放在layouts这个目录下的home.blade.php2.设置内容区域yield(content)3.在其他页面使用模板引擎,先继承,然后在使用section即可extends(layouts.home)section(content)I a…

oracle11g备份出错,Oracle 11g备份导入12c错误

Oracle 11g备份导入12c错误Oracle11g:用户名:FJCPP 表空间:FYSOFT_DATA01 临时表空间:FYSOFT_DATA01导入:expdp FJCPP/FJCPP DIRECTORYdump_dir DUMPFILEFJCPP_20190717_1517_137.dmp logfileFJCPP_20190717_1517_137.…

matlab数字图像处理课程设计报告,数字图像处理课程设计实验报告.doc

数字图像处理课程设计实验报告数字图像处理课程设计题 目:数字图像处理及Huufman(或小波变换)编码仿真实现学生姓名:学 院:信息工程学院系 别:电子信息工程系专 业:电子信息工程班 级:电子指导教师&#xf…