ホームページ  >  記事  >  バックエンド開発  >  PHPリソースタイプの共有例

PHPリソースタイプの共有例

小云云
小云云オリジナル
2018-03-15 14:48:201520ブラウズ

PHP では、リソースタイプ変数をよく使用します。例: mysql 接続、ファイル ハンドルなど。これらの変数はスカラーで表現できないので、PHP のリソース変数を Zend カーネルの C 言語のリソースに接続するにはどうすればよいでしょうか?

1. PHP でのリソース変数の使用

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


印刷結果: resource(5) タイプ (ストリーム)

番号 5: リソース ID が 5 であることを示します。具体的な意味は後で説明します。後で。

stream: リソースタイプ名。

2. リソース ID

カーネルは、登録されたリソース変数を HashTable に保存し、リソースが配置されている HashTable 内のキーをリソース ID として使用します。

つまり、実際には、PHP のリソース変数には整数が格納されており、HashTable 内の対応するリソースはこの ID を通じて検索されます。

  1. #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 関数を実装します:

  1. 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 関数を実装します。

  1. 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 のカスタム拡張機能のメソッドを使用します

  1. my_fwrite($fp, "aaTest");  
      
    var_dump($fp);  
      
    my_fclose($fp);  
      
    var_dump($fp);

通常どおりリソースを閉じます。

7. PHP ではデータベース接続リソースとファイル ハンドル リソースをよく使用しますが、通常はそれらを手動で解放する必要はなく、メモリ リークの問題は発生しません。

  1. my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型

元の登録されたリソースタイプに戻り、zend_register_list_destructors_ex の最初のパラメータを確認します。このパラメータはデストラクタへのポインタです。

その後、自動解放機能を実装する必要がある場合は、デストラクターを定義して関数ポインターを渡すだけで済みます。

別の質問を見てください:

  1. $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(&#39;a.txt&#39;,&#39;r&#39;);//使用fopen函数打开一个文件获取句柄。  
fread($file,1024);//之后把该句柄传递给fread函数,即可对此文件进行后续操作。

例2、データベース操作の例:

コード例:

<?php
$result=mysql_query(&#39;select
 * from tbale&#39;);//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リソースタイプの共有例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。