日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

php 结构体_PHP底层原理知其然知其所以然

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php 结构体_PHP底层原理知其然知其所以然 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1·、PHP變量的底層實現

PHP代碼執行圖解

1.1:變量在內存中的存儲結構

PHP變量是通過zval結構體來存儲的,文件: Zend/zend.h 316行左右

1.2:值的存儲

PHP變量的值是放在zval結構體中的value段中的,文件: Zend/zend.h

1.3:結構體的字段解釋

struct _zval_struct {

/* Variable information */

zvalue_value value; /*變量的值,是個聯合體*/

zend_uint refcount__gc; /*指向次數*/

zend_uchar type; /* 變量類型 */

zend_uchar is_ref__gc; /*是否引用*/

};

type字段的值為以下常量

IS_NULL, IS_BOOL,IS_LONG,IS_DOUBLE

IS_STRING,IS_ARRAY,IS_OBJECT

IS_RESOURCE

1.4:聯合體中的值

typedef union _zvalue_value {

long lval; /* long value */

double dval; /* double value */

struct {

char *val;

int len;

} str;

HashTable *ht; /* hash table value */

zend_object_value obj;

} zvalue_value;

聯合中為什么只列出了5種值?

NULL不用,zval的type為IS_NULL即可

Bool以1,0存儲在lval上

resource的type為resource,其resource的內容用long來標志(資源標記)

1.5:變量的結構圖

1.6:變量的創建

創建變量的步驟: $str = "hello";

1:創建zval結構,并設置其類型 IS_STRING

2:設置其值為 hello

3:講其加入符號表?

{

? ? zval *fooval;

? ? MAKE_STD_ZVAL(fooval);

? ? ZVAL_STRING(fooval, "hello", 1);

? ? ZEND_SET_SYMBOL( EG(active_symbol_table) ,? "foo" , fooval);

}

1.7:符號表 symbol_table

符號表是什么?

符號表是一張哈希表,里面存儲了變量名->變量的zval結構體的地址,

// zend/zend_globals.h 182行

struct _zend_executor_globals {

? ? ...

? ? ...

HashTable *active_symbol_table; /*活動符號表*/

HashTable symbol_table; /* 全局符號表 */

HashTable included_files; /* files already included */

1.8:符號表與函數

Zend/zend_compiles.h

struct _zend_execute_data {

? ? ...

? ? zend_op_array *op_array; //函數的執行步驟

? ? HashTable *symbol_table; // 此函數的符號表地址

? ? zend_class_entry *current_scope;

? ? zval *current_this;

? ? zval *current_object;

? ? ...

};

上面這個,是當前函數執行時的符號表

1.9:符號表與作用域

當執行到函數時,會生成函數的"執行環境結構體",包含函數名,參數,執行步驟,所在的類(如果是方法),以及為這個函數生成一個符號表.符號表統一放在棧上.并把active_symbol_table指向剛產生的符號表

1.10:函數中靜態變量的實現

2.0:常量-常量結構體

結構體 Zend/constants.h 33行

typedef struct _zend_constant {

zval value;? //變量結構體

int flags;? ? //標志,是否大小寫敏感等

char *name; //常量名

uint name_len;

int module_number;//模塊名

} zend_constant;

2.1:常量的生成

int zend_register_constant(zend_constant *c TSRMLS_DC) {

...

...

zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE)

...

...

}

2.2:define函數的實現

define函數當然是調用zend_register_constant聲明的常量 :)?

具體如下 Zend/zend_builtin_functions.c

關鍵代碼:

c.value = *val;

zval_copy_ctor(&c.value);

if (val_free) {

zval_ptr_dtor(&val_free);

}

c.flags = case_sensitive; /* non persistent */

c.name = zend_strndup(name, name_len);

c.name_len = name_len+1;

c.module_number = PHP_USER_CONSTANT;

if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {

RETURN_TRUE;

} else {

RETURN_FALSE;

}

2.3:有趣的測試

1:常量并沒有檢測名字...

define('^_^',"laugh");

2:常量的第2個參數還可以是對象,與手冊上介紹的不同

define('obj',new className());

(當然,對象要有toString方法等著)

2.4:常量為什么是全局有效的?

很簡單,常量的哈希表只有一個

EG(zend_constants)

3.0:內存管理與垃圾回收

PHP封裝了對系統內存的請求,不要直接用malloc直接請求內存

3.1:PHP的hashtable太強大

3.2:引用計數

$a = 1;

$b = $a;

?>

$a,$b的值及類型 都一樣,有必要再申請一個zval結構嗎?

3.3:引用計數解釋

$a = 1;

$b = $a;

?>

當$a的值賦給$b時,并沒有為$b生成一個新的zval結構體.而是$b與$a共享一個結構體.

3.4:copy-on-write 寫時復制

$a = 1;

$b = $a;

$b=6

?>

3.5:引用傳值發生了什么?

$a = 1;

$b = &$a;

?>

3.6:引用傳值為什么影響了2個值

$a = 1;

$b = &$a;

$b = 6;

?>

內核修改zval的值時,發現is_ref_gc為1,則直接修改該value,而不是復制一份.如下圖:

總結

以上是生活随笔為你收集整理的php 结构体_PHP底层原理知其然知其所以然的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。