当前位置: 首页 > 后端技术 > PHP

php底层原理之变量(一)

时间:2023-03-29 20:14:22 PHP

上次和大家聊了垃圾回收机制后,有小伙伴对底层原理比较感兴趣,私信问我一些关于变量的知识,大家比较多对变量感兴趣,所以这次我们就系统的讲讲变量的底层原理变量结构首先我们先说我们的zval结构,即PHP中所有的变量都会以zval结构的形式实现struct_zval_struct{union{long左瓦尔;双dval;结构{字符*val;国际长度;海峡;哈希表*ht;zend_object_value对象;}价值;//变量值zend_uintrefcount__gc;//引用计数内存使用次数,如果为0,删除这个变量zend_uchar类型;//变量类型zend_ucharis_ref__gc;//区分是否是引用变量,如果是引用则为1,否则为0};从上面结构体的内容可以看出,每个PHP变量都会由变量类型、值、引用计数和是否是引用变量四部分组成。注意:上面的zval结构体是php5.3版本之后php7版本之前的结构体变量类型。看到这里,可能有朋友会问我,php不是有8种数据类型吗?但是为什么对应的zvalue只有5个值呢?原因是这样的。为了节省内存,PHP重用了一些变量类型,并没有一一对应地定义每个变量类型。我们看一下zvalue的每个值对应的变量类型zval.value.lval=>integer,boolean,resourcezval.value.dval=>floatzval.value.str=>stringzval.value.*ht=>arrayzval.value.obj=>object看到这里,你可能会感到惊讶。boolean和resources如何对应zval.value的lval?另外,NULL呢?布尔值就像我们将true和false映射到0同1用于数据库存储,php也是这样做的,所以当php发现zval的type值为boolean时,会将boolean转换为0或1,存入zval.value的lval资源资源中进行比较php特殊变量,PHP会在zval.value的lval中存放每个资源对应的资源ID。常见的资源包括:文件句柄,数据库句柄等,NULL更好理解为NULL,因为可以通过zval本身的类型值来区分,所以NULL值不会存储在zval的值中生成php作为变量动态语言没有先声明变量再赋值的习惯,所以总是直接给变量赋值,那么如何实现呢?例子:$name="徐峥的技术成长之路";变量容器的生成实际上,变量每次被常量赋值,都会生成一个对应的变量容器。前面的例子会生成一个变量容器,容器的类型是字符串类型,value值为徐峥的技术成长路径,此时变量容器的ref_count会加1。变量名是与变量容器相关联,变量名是如何与变量容器相关联?其实它也用到了php的一个内部机制,即哈希表。哈希表中存储了每个变量的变量名和指向zval结构体的指针,从而实现了变量名到变量容器变量作用域的映射上面我们提到了变量名和变量容器映射的概念。对于PHP来说,变量分为全局变量和局部变量;那么,它们都存储在哈希表中吗?其实不是,变量存储也有作用域的概念。全局变量存储在全局符号表中,而局部变量是指函数或对象中的变量,存储在活动符号表中(每个函数或对象单独维护自己的活动符号表。活动符号表的生命周期函数或对象在函数或对象被调用时开始,调用完成时结束)变量销毁变量销毁分为以下几种情况:1.手动销毁2.垃圾收集机制销毁(引用计数清零销毁和根销毁)buffer区域满后销毁)这次主要讲的是手动销毁,也就是unset。每次销毁时,都会销毁符号表中的变量名和对应的zval结构体,并将对应的内存归还给php维护的内存池(根据大小划分到对应的内存列表中memory)至于垃圾回收机制的破坏,如果你不了解它的相关原理,那么建议你看一下我之前写的PHP底层原理垃圾回收机制的文章。变量从生成到销毁讲的就是变量。对于变量的生成,我们以常量赋值为例进行说明,那么变量之间的赋值呢?原理是什么?且听下一章来分解~