文档章节

php扩展变量存储

o_冰茶_o
 o_冰茶_o
发布于 2017/09/11 14:24
字数 648
阅读 3
收藏 0
点赞 0
评论 0

PHP中的变量类型和值是通过C语言实现的,内核具体是如何组织用户在PHP中定义的变量呢?
HashTable在ZE内核中被广泛使用,PHP变量也正是存储在一个HashTable实现的符号表里。当在PHP中调用一个函数或者类时,内核会创建一个新的符号表,这也是为什么在函数中无法使用函数外部定义的变量的原因。(因为他们分属两个符号表,一个当前作用域,一个全局作用域)

现在来看内核中是如何定义作用域的:

struct _zend_executor_globals {  
    //略  
    HashTable symbol_table;//全局变量的符号表  
    HashTable *active_symbol_table;//局部变量的符号表  
    //略  
};  

可以通过EG宏来访问变量符号表,EG(symbol_table)访问全局作用域的变量符号表,EG(active_symbol_table)访问当前作用域的变量符号表。

<?php  
$foo='bar';  
?>  

上面这段代码很简单,创建变量foo,并赋值bar。之后的PHP代码中就可以调用$foo变量了。现在看看PHP中定义的变量,内核中是如何实现的。伪代码:

zval* foo;  
MAKE_STD_ZVAL(foo);  
ZVAL_STRING(foo, "bar", 1);  
ZEND_SET_SYMBOL( EG(active_symbol_table), "foo", foo);  

第一步、创建一个zval结构,并设置类型。第二步、赋值为bar。第三步、将其加入当前作用域符号表,只有这样用户才能在PHP里使用这个变量。
通过简单的这三步,即可实现定义php变量。简单的原因,在于内核为我们提供了强大的宏。现在我们将宏分别展开。
MAKE_STD_ZVAL应用到的宏有:

#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__gc = 1;(z)->is_ref__gc = 0;  

MAKE_STD_ZVAL(foo)展开后得到:

(foo) = (zval *) emalloc(sizeof(zval));  
(foo)->refcount__gc = 1;  
(foo)->is_ref__gc = 0;  

可以看出,MAKE_STD_ZVAL做了三件事:分配内存、初始化zval结构中的refcount、is_ref。
ZVAL_STRING应用到的宏有:

#define ZVAL_STRING(z, s, duplicate) {  \  
        const char *__s=(s);            \  
        Z_STRLEN_P(z) = strlen(__s);    \  
        Z_STRVAL_P(z) = (duplicate?estrndup(__s, Z_STRLEN_P(z)):(char*)__s);\  
        Z_TYPE_P(z) = IS_STRING;        \  
    }  
#define Z_STRLEN_P(zval_p)      Z_STRLEN(*zval_p)  
#define Z_STRLEN(zval)          (zval).value.str.len  
#define Z_STRVAL_P(zval_p)      Z_STRVAL(*zval_p)  
#define Z_STRVAL(zval)          (zval).value.str.val  
#define Z_TYPE_P(zval_p)            Z_TYPE(*zval_p)  
#define Z_TYPE(zval)            (zval).type  
#define IS_STRING               6  

展开后得到:

const char *__s=("foo");  
(foo).value.str.len=strlen(__s);  
(foo).value.str.val=(duplicate?estrndup(__s, (zval).value.str.len):(char*)__s);  
(foo).type=6;  

ZVAL_STRING做的工作是设置数据类型并赋值。ZEND_SET_SYMBOL这里只展开一部分宏,因为它展开后过于复杂。

# define EG(v) (executor_globals.v)  

展开部分后得到:

ZEND_SET_SYMBOL(executor_globals.active_symbol_table, "foo", foo);  //将变量名入当前作用域符号表。

© 著作权归作者所有

共有 人打赏支持
o_冰茶_o
粉丝 0
博文 10
码字总数 3187
作品 0
海淀
高级程序员
PHP Session原理分析

Session是以扩展的形式嵌入到PHP内核的,所以我们可以把Session当成扩展来看待。一般扩展被载入到PHP时会调用扩展的MINIT函数,Session也不例外,当Session被载入到PHP内核时,MINIT函数将会...

我不叫大脸猫 ⋅ 2012/09/13 ⋅ 7

究竟什么是TSRMLS_CC

究竟什么是TSRMLS_CC ============ 翻译:54chen.com 原文地址:http://blog.libssh2.org/index.php?/archives/22-What-the-heck-is-TSRMLS_CC-anyway.html 如果你曾经做过php内核或者是php......

LSGX ⋅ 2016/09/06 ⋅ 0

PHPer面试指南-PHP 篇

本书的 GitHub 地址:https://github.com/todayqq/PHPerInterviewGuide PHP 篇收集了一些常见的基础、进阶面试题,基础的面试题不再作答。 基础篇 Get 和 POST 的区别 Cookie 和 Session 的区...

angkee ⋅ 01/24 ⋅ 0

初步了解 PHP V6 中的新特性

增强对 Unicode 的支持 PHP V6 中的主要特性是增强对 Unicode 的支持。目前,PHP 实际上是一个二进制处理器。PHP V5 没有提供原生的 Unicode 支持;它假定所有字符的长度都为 1 字节,这在处...

红薯 ⋅ 2009/06/07 ⋅ 0

php session操作

启用session 1、php.ini设置session存放位置 session.save_path = "d:tmp" 2、建立d:tmp文件夹 3、重启服务 #index1.php #index2.php //当会话自动开始或者通过 sessionstart() 手动开始的时...

指间沙170305 ⋅ 2016/10/19 ⋅ 0

PHP 学习必备技能(基础略过)

1.面向对象编程 面向对象编程基本概念 类和对象的关系 如何定义类 成员属性(变量) 如何创建对象实例及如何访问对象属性 对象在内存中存在的形式 栈、堆、全局区、常量区和代码区的关系 成员方...

风雪中的舞者 ⋅ 2015/08/05 ⋅ 0

PHP内核探索:变量存储与类型

<?php$foo = 10;$bar = 20; function change() { global $foo;//echo '函数内部$foo = '.$foo.'<br />';//如果不把$bar定义为global变量,函数体内是不能访问$bar的 $bar = 0; $foo++;} cha......

qzxun ⋅ 2014/07/10 ⋅ 0

基于PHP7的PHP扩展开发之十三(进行流的操作)

基于PHP7的PHP扩展开发之十三(进行流的操作) Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流2017-07-2940 阅读 目的:在扩展中进行流的操作。简单来讲就是对一些文件,网络的IO操作。...

Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流 ⋅ 2017/07/29 ⋅ 0

PHP内核介绍及扩展开发指南—基础知识

一、 基础知识 本章简要介绍一些Zend引擎的内部机制,这些知识和Extensions密切相关,同时也可以帮助我们写出更加高效的PHP代码。 1.1 PHP变量的存储 1.1.1 zval结构 Zend使用zval结构来存储...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

PHP中的SQL查询缓存

适合读者 本教程适合于那些对缓存SQL查询以减少数据库连接与执行的负载、提高脚本性能感兴趣的PHP程序员。 概述 许多站点使用数据库作为站点数据存储的容器。数据库包含了产器信息、目录结构...

刘理志 ⋅ 2010/05/20 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

DevOps 资讯 | PostgreSQL 的时代到来了吗 ?

PostgreSQL是对象-关系型数据库,BSD 许可证。拼读为"post-gress-Q-L"。 作者: Tony Baer 原文: Has the time finally come for PostgreSQL?(有删节) 近30年来 PostgreSQL 无疑是您从未听...

RiboseYim ⋅ 5分钟前 ⋅ 0

Cube、Cuboid 和 Cube Segment

1.Cube (或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过 Cube 对数据进行分析,可以大大加快数据的查询效率 2.Cuboid 在 Kylin 中特...

无精疯 ⋅ 43分钟前 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 45分钟前 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 55分钟前 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 58分钟前 ⋅ 0

Redis 注册为 Windows 服务

Redis 注册为 Windows 服务 redis 注册为 windows 服务相关命令 注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 启动服务 re......

Os_yxguang ⋅ 59分钟前 ⋅ 0

世界那么大,语言那么多,为什么选择Micropython,它的优势在哪?

最近国内MicroPython风靡程序界,是什么原因导致它这么火呢?是因为他功能强大,遵循Mit协议开源么? 错!因为使用它真的是太舒服了!!! Micropython的由来,这得益于Damien George这位伟大...

bodasisiter ⋅ 今天 ⋅ 0

docker 清理总结

杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器(docker rm没有加-f参数,运行中的容器不会删掉) docker rm $(docker ps -a -q) 删除所有未打 dangling 标...

vvx1024 ⋅ 今天 ⋅ 0

关于学习

以前学车的时候,教练说了这样的一句话:如果一个人坐在车上一直学,一直学,反而不如大家轮流着学。因为一个人一直学,就没有给自己留空间来反思和改进。而轮流着学的时候大家下来之后思考上...

mskk ⋅ 今天 ⋅ 0

压缩工具之gzip-bzip2-xz

win下常见压缩工具:rar zip 7z linux下常见压缩工具:zip gz bz2 xz tar.gz tar.bz2 tar.xz gzip 不支持目录压缩 gzip 1.txt #压缩。执行后1.txt消失,生成1.txt.gz压缩文件 gzip -d 1.txt....

ZHENG-JY ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部