First, let’s review the structure of zval:
Copy the code The code is as follows:
struct _zval_struct {
* Variable information */
Zvalue_value value;/ * value */
Zend_uint Refcount;
Zend_uchar Type;/ * Active Type */
Zend_uchar is_ref; };
We have never introduced the refcount and is_ref fields. We know that PHP is a long-running server-side script interpreter. So for it, efficiency and resource usage are a very important measurement standard. In other words, PHP must try to introduce memory usage. Consider the following code:
Copy Code The code is as follows:
$var = "laruence";
$var_dup = $var;
unset($var) ;
?>
The first line of code creates a string variable, applies for a 9-byte memory, and saves the string "laruence" and a NULL(/ 0) at the end.
The second line defines a new string variable and "copies" the value of the variable var to this new variable.
The third line unsets the variable var
Code like this is very common in our daily scripts. If PHP reallocates memory and copies data for each variable assignment, then the above code is public You need to apply for 18 bytes of memory space, and we can easily see that the above code actually does not need to apply for two spaces. Haha, PHP developers also saw it:
We have said it before, Variables in PHP are implemented using a symbol name stored in the symbol_table, corresponding to a zval. For example, for the first line of code above, a value "var" will be stored in the symbol_table, corresponding to a pointer pointing to a zval. structure, the variable value "laruence" is stored in this zval, so it is not difficult to imagine that for the above code, we can make the pointers corresponding to "var" and "var_dup" point to the same zval.
PHP also does this. At this time, we need to introduce the refcount field in the zval structure that we have not introduced before.
refcount, as the name suggests, records the count of references to the current zval.
For example, for the code:
Copy the code The code is as follows:
$var = 1 ;
$var_dup = $var;
?>
In the first line, an integer variable is created, and the variable value is 1. At this time, the refcount of the zval that saves integer 1 is 1.
In the second line, a new integer variable is created. The variable also points to the zval just created, and the refcount of this zval is increased by 1. At this time, the refcount of this zval is 2.
PHP provides a function to help us understand this process debug_zval_dump:
Copy code The code is as follows:
< ?php
$var = 1;
debug_zval_dump($var);
$var_dup = $var;
debug_zval_dump($var);
?>
Output:
long(1) refcount(2)
long(1) refcount(3
If you are wondering, the refcount of var should be 1?
We know that for simple variables, PHP passes parameters by value. That is to say, when debug_zval_dump($var) is executed, $var will be passed to debug_zval_dump by value, which will result in var. The refcount increases by 1, so as long as we can see the fact that when a variable is assigned to a variable, it can cause the refcount of zval to increase by 1.
Now let’s look back at the code at the beginning of the article. When the last line of unset( is executed. $var), what will happen? Yes, since refcount is reduced by 1, the above code:
Copy the code The code is as follows:
$var = "laruence";
$var_dup = $var;
unset($var);
debug_zval_dump($var_dup);
?>
Output:
string(8) "laruence" refcount(2
But, what about the code below?
Copy code The code is as follows:
$var = "laruence";
$var_dup = $var;
$var = 1;
?>
Obviously after this code is executed, the value of $var_dup should still be "laruence", so how is this achieved?
This is PHP's copy on write mechanism:
Before modifying a variable, PHP will first check the refcount of the variable. If the refcount is greater than 1, PHP will execute a separate routine. For the above code, When executing the third line, PHP finds that the refcount of the zval pointed to by $var is greater than 1, then PHP will copy a new zval, reduce the refcount of the original zval by 1, and modify the symbol_table so that $var and $var_dup Separation. This mechanism is the so-called copy on write (copy on write).
Upload the code for testing:
Copy the code The code is as follows:
$var = " laruence";
$var_dup = $var;
$var = 1;
debug_zval_dump($var);
debug_zval_dump($var_dup);
?>
Output:
long(1) refcount(2)
string(8) "laruence" refcount(2
Now we know that when using variable copy, PHP It is not a real copy internally, but uses pointing to the same structure to save overhead. So, how to implement references in PHP?
Copy code The code is as follows:
$var = "laruence";
$var_ref = &$var;
$var_ref = 1;
?>
After this code ends, $var will also be indirectly modified to 1. This process is called (change on write: change on write). So how does ZE know? Does this copy not require Separation?
The is_ref field in zval will be used at this time:
For the above code, after the second line is executed, the refcount of zval represented by $var becomes 2, and sets is_ref to 1 at the same time.
When reaching the third line, PHP first checks the is_ref field of zval represented by var_ref. If it is 1, it will not be separated. The general logic is as follows:
Copy code The code is as follows:
if((*val)->is_ref || (*val)->refcount<2) {
🎜>
Copy code
The code is as follows:
$var = "laruence"; $var_dup = $var; $var_ref = &$var;
?>
For the above code, there is a pair of copy on write variables $var and $var_dup, and another How does this situation work for the variable pair $var and $var_ref of the change on write mechanism?
When the second line is executed, as mentioned before, $var_dup and $var point to the same zval. , the refcount is 2.
When executing the third line, PHP finds that the refcount of the zval to be operated is greater than 1, then PHP will execute Separation, separate $var_dup, and change $var and $var_ref on write association. That is, refcount=2, is_ref=1;
Based on this analysis, we can let debug_zval_dump output the result that refcount is 1:
Copy code
The code is as follows:
$var = "laruence"; $var_dup = &$var; debug_zval_dump($var);
?>
Output:
string(8) "laruence" refcount(1
Reader, you can figure out the detailed reason with a little analysis, so I won’t overdo it. ;)This time we introduced PHP’s variable separation mechanism. Next time I will continue to introduce how to receive and send parameters in PHP scripts in extensions.
http://www.bkjia.com/PHPjc/328119.html
www.bkjia.com
true
http: //www.bkjia.com/PHPjc/328119.htmlTechArticleFirst we review the structure of zval: Copy the code as follows: struct _zval_struct { /* Variable information */ zvalue_value value ; /* value */ zend_uint refcount; zend_uchar...