PHP 리소스 유형 예시 공유

小云云
풀어 주다: 2023-03-21 14:24:02
원래의
1516명이 탐색했습니다.

PHP에서는 리소스 유형 변수를 자주 사용합니다. 예: mysql 연결, 파일 핸들 등 이러한 변수는 스칼라로 표시할 수 없습니다. 그렇다면 PHP의 리소스 변수를 Zend 커널의 C 언어 리소스에 어떻게 연결합니까?

1. PHP에서 리소스 변수 사용

  1. $fp = fopen("test.txt", "rw");  
      
    var_dump($fp);  
      
    fclose($fp);
    로그인 후 복사


인쇄 결과: (스트림) 유형의 리소스(5)

숫자 5: 리소스 ID가 5임을 나타냅니다. 구체적인 의미가 소개됩니다. 나중에.

stream: 리소스 유형 이름.

2. 리소스 ID

커널은 등록된 리소스 변수를 HashTable에 저장하고, 리소스가 위치한 HashTable의 키를 리소스 ID로 사용합니다.

그래서 사실 PHP의 리소스 변수는 실제로 정수를 저장하는데, 이 ID를 통해 HashTable의 해당 리소스를 찾습니다.

  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

이해의 편의를 위해 초기화 시 커널에 새로운 리소스 유형을 등록하는 확장이라고 생각하면 됩니다.

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 찾기 (regular_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 resources_PHP 튜토리얼

PHP 리소스

라이브러리, 프레임워크, 템플릿 등을 포함한 PHP 리소스 요약

위 내용은 PHP 리소스 유형 예시 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿