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

[经验分享] [译]变量在 PHP7 内部的实现(二)

[复制链接]

尚未签到

发表于 2018-12-13 13:12:37 | 显示全部楼层 |阅读模式
翻译  Dec 21, 2015
  本文第一部分和第二均翻译自Nikita Popov(nikicPHP 官方开发组成员柏林科技大学的学生) 的博客。为了更符合汉语的阅读习惯文中并不会逐字逐句的翻译。
  要理解本文你应该对 PHP5 中变量的实现有了一些了解本文重点在于解释 PHP7 中 zval 的变化。
  第一部分讲了 PHP5 和 PHP7 中关于变量最基础的实现和变化。这里再重复一下主要的变化就是 zval 不再单独分配内存不自己存储引用计数。整型浮点型等简单类型直接存储在 zval 中。复杂类型则通过指针指向一个独立的结构体。
  复杂的 zval 数据值有一个共同的头其结构由 zend_refcounted 定义
struct _zend_refcounted {  
    uint32_t refcount;
  
    union {
  
        struct {
  
            ZEND_ENDIAN_LOHI_3(
  
                zend_uchar    type,
  
                zend_uchar    flags,
  
                uint16_t      gc_info)
  
        } v;
  
        uint32_t type_info;
  
    } u;};
  这个头存储有 refcount引用计数值的类型 type 和循环回收的相关信息 gc_info 以及类型标志位flags。
  接下来会对每种复杂类型的实现单独进行分析并和 PHP5 的实现进行比较。引用虽然也属于复杂类型但是上一部分已经介绍过了这里就不再赘述。另外这里也不会讲到资源类型因为作者觉得资源类型没什么好讲的。
字符串
  PHP7 中定义了一个新的结构体 zend_string 用于存储字符串变量
struct _zend_string {  
    zend_refcounted   gc;
  
    zend_ulong        h;        /* hash value */
  
    size_t            len;
  
    char              val[1];};
  除了引用计数的头以外字符串还包含哈希缓存 h字符串长度 len 以及字符串的值 val。哈希缓存的存在是为了防止使用字符串做为 hashtable 的 key 在查找时需要重复计算其哈希值所以这个在使用之前就对其进行初始化。
  如果你对 C 语言了解的不是很深入的话可能会觉得 val 的定义有些奇怪这个声明只有一个元素但是显然我们想存储的字符串长度肯定大于一个字符的长度。这里其实使用的是结构体的一个『黑』方法在声明数组时只定义一个元素但是实际创建 zend_string 时再分配足够的内存来存储整个字符串。这样我们还是可以通过 val 访问完整的字符串。
  当然这属于非常规的实现手段因为我们实际的读和写的内容都超过了单字符数组的边界。但是 C 语言编译器却不知道你是这么做的。虽然 C99 也曾明确规定过支持『柔性数组』但是感谢我们的好朋友微软没人能在不同的平台上保证 C99 的一致性所以这种手段是为了解决 Windows 平台下柔性数组的支持问题。
  新的字符串类型的结构比原生的 C 字符串更方便使用第一是因为直接存储了字符串的长度这样就不用每次使用时都去计算。第二是字符串也有引用计数的头这样也就可以在不同的地方共享字符串本身而无需使用 zval。一个经常使用的地方就是共享 hashtable 的 key。
  但是新的字符串类型也有一个很不好的地方虽然可以很方便的从 zend_string 中取出 C 字符串使用 str->val 即可但反过来如果将 C 字符串变成 zend_string 就需要先分配 zend_string 需要的内存再将字符串复制到 zend_string 中。这在实际使用的过程中并不是很方便。
  字符串也有一些特有的标志存储在 GC 的标志位中的
#define IS_STR_PERSISTENT           (1

运维网声明 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-650972-1-1.html 上篇帖子: [译]变量在 PHP7 内部的实现(一) 下篇帖子: php获取js设置的cookie,解决无法得到中文的问题。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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