Skip to content

Commit 231a068

Browse files
committed
update
1 parent 6cf83f6 commit 231a068

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

zval.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# 变量的内部实现
1+
## 2.1 变量的内部实现
22

33
PHP变量实现的基础结构是`zval`,各种类型的实现均基于此结构实现,是PHP中最基础的一个结构,每个PHP变量都对应一个`zval`,下面就看下这个结构以及PHP变量的内存管理机制。
44

5-
## 1.zval结构
5+
### 2.1.1 zval结构
66
```c
77
//zend_type.h
88
typedef struct _zval_struct zval;
@@ -56,7 +56,7 @@ struct _zval_struct {
5656

5757
`zend_value`可以看出,除`long``double`类型直接存储值外,其它类型都为指针,指向各自的结构。
5858

59-
## 2.类型
59+
### 2.1.2 类型
6060
`zval.u1.type`类型:
6161
```c
6262
/* regular data types */
@@ -85,10 +85,10 @@ struct _zval_struct {
8585
#define IS_PTR 17
8686
```
8787

88-
### 2.1 基本类型
88+
#### 2.1.2.1 基本类型
8989
最简单的类型是true、false、long、double、null,其中true、false、null没有value,直接根据type区分,而long、double的值则直接存在value中:zend_long、double。
9090

91-
### 2.2 字符串
91+
#### 2.1.2.2 字符串
9292
PHP中字符串通过`zend_string`表示:
9393
```c
9494
struct _zend_string {
@@ -103,7 +103,7 @@ struct _zend_string {
103103
* __len:__字符串长度,通过这个值保证二进制安全
104104
* __val:__字符串内容,变长struct,分配时按len长度申请内存
105105

106-
### 2.3 数组
106+
#### 2.1.2.3 数组
107107
array是PHP中非常强大的一个数据结构,它的底层实现就是普通的有序HashTable,这里简单看下它的结构,下一节会单独分析数组的实现。
108108

109109
```c
@@ -131,7 +131,7 @@ struct _zend_array {
131131
dtor_func_t pDestructor;
132132
};
133133
```
134-
### 2.4 对象/资源
134+
#### 2.1.2.4 对象/资源
135135
```c
136136
struct _zend_object {
137137
zend_refcounted_h gc;
@@ -151,8 +151,8 @@ struct _zend_resource {
151151
```
152152
对象比较常见,资源指的是tcp连接、文件句柄等等类型,这种类型比较灵活,可以随意定义struct,通过ptr指向,后面会单独分析这种类型,这里不再多说。
153153

154-
### 2.5 引用
155-
引用是PHP中比较特殊的一种类型,它实际是指向另外一个PHP变量,对它的修改会直接改动实际指向的zval,可以简单的理解为C中的指针,在PHP中通过`&`操作符产生一个引用变量。
154+
#### 2.1.2.5 引用
155+
引用是PHP中比较特殊的一种类型,它实际是指向另外一个PHP变量,对它的修改会直接改动实际指向的zval,可以简单的理解为C中的指针,在PHP中通过`&`操作符产生一个引用变量,也就是说不管以前的类型是什么,`&`首先会将新生成一个zval,类型为IS_REFERENCE,然后将val的value指向原来zval的value
156156
```c
157157
struct _zend_reference {
158158
zend_refcounted_h gc;
@@ -183,14 +183,14 @@ $c = &$b;/*或$c = &$a*/ //$a,$b,$c -> zend_reference_1(refcount=3) -> zend_
183183
```
184184
这个也表示PHP中的__引用只可能有一层____不会出现一个引用指向另外一个引用的情况__,也就是没有C语言中`指针的指针`的概念。
185185

186-
## 3.内存管理
186+
### 2.1.3 内存管理
187187
接下来分析下变量的分配、销毁。
188188

189189
在分析变量内存管理之前我们先自己想一下可能的实现方案,最简单的处理方式:定义变量时alloc一个zval及对应的value结构(ref/arr/str/res...),赋值、函数传参时硬拷贝一个副本,这样各变量最终的值完全都是独立的,不会出现多个变量同时共用一个value的情况,在执行完以后直接将各变量及value结构free掉。
190190

191191
这种方式是可行的,而且内存管理也很简单,但是,硬拷贝带来的一个问题是效率低,比如我们定义了一个变量然后赋值给另外一个变量,可能后面都只是只读操作,假如硬拷贝的话就会有多余的一份数据,这个问题的解决方案是:__引用计数+写时复制__。PHP变量的管理正是基于这两点实现的。
192192

193-
### 3.1 引用计数
193+
#### 2.1.3.1 引用计数
194194
引用计数是指在value中增加一个字段`refcount`记录指向当前value的数量,变量复制、函数传参时并不直接硬拷贝一份value数据,而是将`refcount++`,变量销毁时将`refcount--`,等到`refcount`减为0时表示已经没有变量引用这个value,将它销毁即可。
195195
```php
196196
$a = "time:" . time(); //$a -> zend_string_1(refcount=1)
@@ -252,7 +252,7 @@ simple types很显然用不到,不再解释,string、array、object、resour
252252

253253
* __immutable array:__只有在用opcache的时候才会用到这种类型,不清楚具体实现,暂时忽略。
254254

255-
### 3.2 写时复制
255+
#### 2.1.3.2 写时复制
256256
上一小节介绍了引用计数,多个变量可能指向同一个value,然后通过refcount统计引用数,这时候如果其中一个变量试图更改value的内容则会重新拷贝一份value修改,同时断开旧的指向,写时复制的机制在计算机系统中有非常广的应用,它只有在必要的时候(写)才会发生硬拷贝,可以很好的提高效率,下面从示例看下:
257257

258258
```php
@@ -289,10 +289,10 @@ __copyable__的意思是当value发生duplication时是否需要copy,这个具
289289

290290
具体literal、局部变量区变量的初始化、赋值后面编译、执行两篇文章会具体分析,这里知道变量有个`copyable`的属性就行了。
291291

292-
### 3.3 变量回收
292+
#### 2.1.3.3 变量回收
293293
PHP变量的回收主要有两种:主动销毁、自动销毁。主动销毁指的就是__unset__,而自动销毁就是PHP的自动管理机制,在return时减掉局部变量的refcount,即使没有显式的return,PHP也会自动给加上这个操作。
294294

295-
### 3.4 垃圾回收
295+
#### 2.1.3.4 垃圾回收
296296
PHP变量的回收是根据refcount实现的,当unset、return时会将变量的引用计数减掉,如果refcount减到0则直接释放value,这是变量的简单gc过程,但是实际过程中出现gc无法回收导致内存泄漏的bug,先看下一个例子:
297297

298298
```php
@@ -329,7 +329,7 @@ unset($a);
329329
```
330330
具体的垃圾回收过程这里不再介绍,后面会单独分析。
331331

332-
## 4.参考资料
332+
### 2.1.4 参考资料
333333

334334
[《Internal value representation in PHP 7 - Part 1》](https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html)
335335

0 commit comments

Comments
 (0)