PHP では、リソースタイプ変数をよく使用します。例: mysql 接続、ファイル ハンドルなど。これらの変数はスカラーで表現できないので、PHP のリソース変数を Zend カーネルの C 言語のリソースに接続するにはどうすればよいでしょうか?
1. PHP でのリソース変数の使用
$fp = fopen("test.txt", "rw"); var_dump($fp); fclose($fp);
印刷結果: resource(5) タイプ (ストリーム)
番号 5: リソース ID が 5 であることを示します。具体的な意味は後で説明します。後で。
stream: リソースタイプ名。
2. リソース ID
カーネルは、登録されたリソース変数を HashTable に保存し、リソースが配置されている HashTable 内のキーをリソース ID として使用します。
つまり、実際には、PHP のリソース変数には整数が格納されており、HashTable 内の対応するリソースはこの ID を通じて検索されます。
#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 であり、実際に整数変数への代入であることがわかります。
3. リソースタイプ名
リソースタイプを区別するには、定義するリソースのタイプ名を定義する必要があります。
#define MY_RES_NAME "my_resource" //资源类型名称,PHP通过var_dump打印资源变量时会看到这个名称 static int my_resource_descriptor; ZEND_MINIT_FUNCTION(jinyong) { my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型 }
ZEND_MINIT_FUNCTION(jinyong) は、PHP が SAPI としてメモリにロードされるときに、すべての拡張機能 (Apache の mod_php5 拡張機能など) の ZEND_MINIT_FUNCTION を実行します。
ここで、jinyong は現在の拡張機能の名前です。例えば、この時の拡張機能の名前はjinyongです
理解を容易にするために、初期化時に新しいリソースタイプをカーネルに登録する拡張機能と考えます。
4. リソース変数を作成します
リソースタイプが正常に登録され、リソースに対して区別されたタイプ名が定義されました。このリソースの変数が使用できるようになりました。
PHP で fopen 関数を実装します:
PHP_FUNCTION(my_fopen) { zval *res; char *filename, *mode; int filename_strlen, mode_strlen; FILE *fp; if(zend_parse_parameters(ZEND_NUM_ARGS TSRMLS_CC, "s|s", &filename, &filename_strlen, &mode, &mode_strlen) == FAILURE){ RETURN_FALSE; } //此处省略了对参数的有效性验证 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 関数を実装します。
PHP_FUNCTION(my_fclose) { zval *res; FILE *fp; if(zend_parse_parameters(ZEND_NUM_ARGS TSRMS_CC, "r", &res) == FAILURE){ RETURN_FALSE; } if(Z_TYPE_P(res) == IS_RESOURCE){//判断变量类型是否是资源类型 zend_hash_index_del(&EG(regular_list), Z_RESVAL_P(res));//EG就类似于PHP中的$_GLOBALS。在全局资源变量regular_list中删除对应ID的资源 }else{ php_error_docref(NULL TSRMLS_CC, E_WARNING, "参数必须是资源类型变量"); RETURN_FALSE; } RETURN_TRUE; }
は、PHP で my_fclose という名前の関数を定義します。 my_fclose($resource)
5. 拡張機能をコンパイルしてインストールし、php-fpm または mod_php5 などを再起動します
6. PHP のカスタム拡張機能のメソッドを使用します
my_fwrite($fp, "aaTest"); var_dump($fp); my_fclose($fp); var_dump($fp);
通常どおりリソースを閉じます。
7. PHP ではデータベース接続リソースとファイル ハンドル リソースをよく使用しますが、通常はそれらを手動で解放する必要はなく、メモリ リークの問題は発生しません。
my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型
元の登録されたリソースタイプに戻り、zend_register_list_destructors_ex の最初のパラメータを確認します。このパラメータはデストラクタへのポインタです。
その後、自動解放機能を実装する必要がある場合は、デストラクターを定義して関数ポインターを渡すだけで済みます。
別の質問を見てください:
$fp = fopen("test.txt", "rw"); var_dump($fp); //fclose($fp); 此处不使用fclose释放资源 unset($fp); //而是使用unset释放 //unset没有问题,会正常释放$fp变量。但$fp对应真正的打开文件资源句柄资源将永远释放不了,直至mod_php5或php-fpm重启 //可以看出,在注册资源类型时定义析构函数的必要性了
デストラクターを定義します:
static void php_myres_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){//析构函数被调用时,会接受一个当前资源变量的参数 FILE *fp = (FILE*)rsrc->ptr; fclose(fp); } ZEND_MINIT_FUNCTION(jinyong) { my_resource_descriptor = zend_register_list_destructors_ex(php_myres_dtor, NULL, MY_RES_NAME, module_number); }
PHP では、いわゆるリソース変数は実際にはカーネルのグローバル リソース変数リスト EG に整数値を格納します。対応するものを見つけます。 (register_list) 内のポインターを指定し、対応する操作を実行します。
リソースタイプは、外部リソースへの参照を保持する特別な変数です。リソースは、特殊な機能を通じて作成および使用されます。
データベース接続、ファイルを開く、グラフィックキャンバス領域など。
リソースタイプは実際には単なる整数であり、カーネルはこの整数値に基づいてリソースプールに似た場所に移動して、最終的に必要なデータを見つけることができます。
例1、ファイル操作の例:
コード例:
<?php $file=fopen('a.txt','r');//使用fopen函数打开一个文件获取句柄。 fread($file,1024);//之后把该句柄传递给fread函数,即可对此文件进行后续操作。
例2、データベース操作の例:
コード例:
<?php $result=mysql_query('select * from tbale');//mysql_query函数执行一条sql,若失败,返回false;成功,查询结果被缓存,并返回资源标识(类似:Resource id#42)即指向该资源的句柄。 mysql_num_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询出来的条数 mysql_fetch_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询结构
説明:
リソースを使用および破棄する関数のリスト。
is_resource() 関数を使用すると、変数がリソースかどうかを判断でき、関数 get_resource_type() はリソースのタイプを返します。
PHP リソース変数に関しては、MYSQL 接続が解放されないなどの問題を心配する必要はありません。拡張機能にはデストラクター メソッドが定義されており、自動的に解放されるようにサポートされています。
関連する推奨事項:
PHP リソース リスト、php リソース_PHP チュートリアル
ライブラリ、フレームワーク、テンプレートなどを含む PHP リソースの概要
以上がPHPリソースタイプの共有例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。