设为首页 收藏本站
查看: 631|回复: 0

[经验分享] PHP变量的存储方式

[复制链接]

尚未签到

发表于 2017-3-26 11:29:36 | 显示全部楼层 |阅读模式
  当用户在PHP中调用一个函数或者类的方法时,内核会创建一个新的符号表并激活之,这也就是为什么我们无法在函数中使用在函数外定义的变量的原因(因为它们分属两个符号表,一个当前作用域的,一个全局作用域的)。如果不是在一个函数里,则全局作用域的符号表处于激活状态。
  我们现在打开Zend/zend_globals.h文件,看一下_zend_execution_globals结构体,会在其中发现这么两个element:

struct _zend_executor_globals {
...
HashTable symbol_table;
HashTable *active_symbol_table;
...
};
  其中的 symbol_table元素可以通过EG宏来访问,它代表着PHP的全局变量,如$GLOBALS,其实从根本上来讲,$GLOBALS不过是EG(symbol_table)的一层封装而已。EG宏在Zend\zend_globals_macros在被定义:

/* Executor */
#ifdef ZTS
# define EG(v) TSRMG(executor_globals_id, zend_executor_globals *, v)
#else
# define EG(v) (executor_globals.v)
extern ZEND_API zend_executor_globals executor_globals;
#endif
  symbol_table和active_symbol_table在_zend_executor_globals里虽然都代表HashTable,但一个是真正的HashTable,而另一个是一个指针。当
我们在对HashTable进行操作的时候,往往是把它的地址传递给一些函数。所以,如果我们要对EG(symbol_table)的结果进行操作,往往
需要对它进行求址操作然后用它的地址作为被调用函数的参数。
  下面我们用一段例子来解释下上面说的理论:

<?php
$foo = 'bar';
?>
   上面是一段PHP语言的例子,我们创建了一个变量,并把它的值设置为'bar',在以后的代码中我们便可以使用$foo变量。相同的功能我们怎样在内核中实现呢?我们可以先构思一下步骤:


  • 创建一个zval结构,并设置其类型。
  • 设置值为'bar'。
  • 将其加入当前作用域的符号表,只有这样用户才能在PHP里使用这个变量。
  具体的代码为:.

{
zval *fooval;
MAKE_STD_ZVAL(fooval);
ZVAL_STRING(fooval, "bar", 1);
ZEND_SET_SYMBOL( EG(active_symbol_table) ,  "foo" , fooval);
}
   首先,我们声明一个zval指针,并申请一块内存。然后通过ZVAL_STRING宏将值设置为‘bar’,最后一行的作用就是将这个zval加入到当前的符号表里去,并将其label定义成foo,这样用户就可以在代码里通过$foo来使用它了。
  以下是用的宏:

#define MAKE_STD_ZVAL(zv) \
ALLOC_ZVAL(zv); \
INIT_PZVAL(zv);
/* fast cache for zval's */
#define ALLOC_ZVAL(z)\
(z) = (zval *) emalloc(sizeof(zval))
#define INIT_PZVAL(z)\
(z)->refcount__gc = 1;\
(z)->is_ref__gc = 0;
#define ZVAL_STRING(z, s, duplicate) do {\
const char *__s=(s);\
zval *__z = (z);\
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;\
} while (0)
#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)) {\
Z_SET_REFCOUNT_P(var, Z_REFCOUNT_PP(orig_var));\
Z_SET_ISREF_P(var);\
\
if (_refcount) {\
Z_SET_REFCOUNT_P(var, Z_REFCOUNT_P(var) + _refcount - 1);\
}\
zval_dtor(*orig_var);\
**orig_var = *(var);\
FREE_ZVAL(var);\
} else {\
Z_SET_ISREF_TO_P(var, _is_ref);\
if (_refcount) {\
Z_SET_REFCOUNT_P(var, _refcount);\
}\
zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL);\
}\
}
 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-355575-1-1.html 上篇帖子: PHP读取打包JS文件 下篇帖子: PHP缓存机制的入门
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表