PHP資源型別

2022-04-11 22:32:24 字數 3232 閱讀 6393

在php中,我們經常使用到資源型別變數。例如:mysql連線、檔案控制代碼等。

這些變數無法使用標量來表示,那麼在zend核心中是如何將php中的資源變數與c語言中的資源銜接的呢?

一、資源變數在php中的使用

[php]view plain

copy

$fp = fopen("test.txt", "rw");  

var_dump($fp);  

fclose($fp);  

列印結果:resource(5) of type (stream)

數字5:表示資源id為5,具體含義後面介紹。

stream:資源型別名稱。

二、資源id

核心中將註冊的資源變數儲存在乙個hashtable中,並把資源所在hashtable中的key作為資源id。

所以,實際上php中的資源變數實際儲存的是乙個整型,通過這個id找到hashtable中對應的資源。

[cpp]view plain

copy

#define z_resval(zval)          (zval).value.lval  

#define z_resval_p(zval)        z_resval(*zval)  

#define z_resval_pp(zval)       z_resval(**zval)  

上面的巨集,是核心中ze為資源變數賦值的api,看出確實是對整型變數的賦值。

三、資源型別名稱

為了區分資源型別,需要為我們定義的資源定義型別名稱。

[cpp]view plain

copy

#define my_res_name "my_resource" //資源型別名稱,php通過var_dump列印資源變數時會看到這個名稱  

static int my_resource_descriptor;  

zend_minit_function(jinyong)  

zend_minit_function(jinyong)會在php作為sapi(例如,apache的mod_php5擴充套件)被載入到記憶體時,會執行所有擴充套件的zend_minit_function。

其中jinyong,是當前擴充套件的名字。例如此時擴充套件的名字就是jinyong

這裡為了方便理解,我們就把它認為是擴充套件在初始化時,會向核心中註冊新的資源型別。

四、建立資源變數

資源型別已經註冊成功,也為資源定義了區分的型別名稱。現在可以使用這種資源的變數了。

實現php中的fopen函式:

[cpp]view plain

copy

php_function(my_fopen)  

//此處省略了對引數的有效性驗證  

fp = fopen(filename, mode);  

zend_register_resource(res, fp, my_resource_descriptor);//向全域性變數&eg(regular_list)中註冊資源變數,並將對應hashtable的id賦值給res  

return_resource(res);//向php返回資源變數  

}  這裡,定義了php中名稱為my_fopen的函式。my_fopen(string $file_name, string $mode)

實現php中的fclose函式:

[cpp]view plain

copy

php_function(my_fclose)  

if(z_type_p(res) == is_resource)else  

return_true;  

}  定義了php中名稱為my_fclose的函式。my_fclose($resource)

五、編譯、安裝擴充套件,重啟php-fpm或mod_php5等

六、php中使用自定義擴充套件中的方法

[php]view plain

copy

my_fwrite($fp, "aatest");  

var_dump($fp);  

my_fclose($fp);  

var_dump($fp);  

可以正常,開啟和關閉資源。

七、我們在php中經常使用資料庫連線資源、檔案控制代碼資源,但他們通常無需我們手工釋放,也不會出現記憶體洩漏問題,這是如何實現的呢?

[cpp]view plain

copy

my_resource_descriptor = zend_register_list_destructors_ex(null, null, my_res_name, module_number);//向核心中註冊新的資源型別  

回到最開始的註冊資源型別,看到zend_register_list_destructors_ex的第乙個引數,這個引數就是析構函式的指標。

那麼,如果需要實現自動釋放功能,只需要定義析構函式並傳遞函式指標即可。

再看乙個問題:

[php]view plain

copy

$fp = fopen("test.txt", "rw");  

var_dump($fp);  

//fclose($fp); 此處不使用fclose釋放資源  

unset($fp); //而是使用unset釋放  

//unset沒有問題,會正常釋放$fp變數。但$fp對應真正的開啟檔案資源控制代碼資源將永遠釋放不了,直至mod_php5或php-fpm重啟  

//可以看出,在註冊資源型別時定義析構函式的必要性了  

定義析構函式:

[cpp]view plain

copy

static void php_myres_dtor(zend_rsrc_list_entry *rsrc tsrmls_dc)  

zend_minit_function(jinyong)  

[cpp]view plain

copy

在php中,所謂資源變數,實際都是通過儲存整型值,在到核心全域性資源變數列表eg(regular_list)中找到對應的指標,並進行相應操作。  

而php資源變數,之所以不用擔心類似mysql連線未釋放問題,也是因為擴充套件中定義了析構方法,幫助自動釋放。 

PHP資源型別

分類 linux phpc c 2012 05 14 22 45 6693人閱讀收藏 舉報php zend descriptor fpfunction list 在php中,我們經常使用到資源型別變數。例如 mysql連線 檔案控制代碼等。這些變數無法使用標量來表示,那麼在zend核心中是如何將ph...

資源型別Resource Types

目錄directory 資源型別resource types res anim xml檔案,它們被編譯進逐幀動畫 frame by frame animation 或補間動畫 tweened animation 物件res drawable png 9.png jpg檔案,它們被編譯進以下的draw...

Android應用開發(10) 資源型別

本節中的每個頁面都描述了 您可以在專案資源目錄 中提供 的某種型別的 應用程式資源 的用法,格式和語法res 以下是每個頁面的簡要摘要 動畫資源 定義預先確定的動畫。補間動畫儲存在課程中 res anim 並從r.anim課程 中進行訪問 框架動畫儲存在類中 res drawable 並從中訪問r....