In PHP, we often use resource type variables. For example: mysql connection, file handle, etc. These variables cannot be represented by scalars, so how do you connect resource variables in PHP to resources in C language in the Zend kernel?
1. The use of resource variables in PHP
$fp = fopen("test.txt", "rw"); var_dump($fp); fclose($fp);
##Print results: resource(5) of type (stream)
#define Z_RESVAL(zval) (zval).value.lval #define Z_RESVAL_P(zval) Z_RESVAL(*zval) #define Z_RESVAL_PP(zval) Z_RESVAL(**zval)
#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) will be loaded in PHP as a SAPI (for example, Apache's mod_php5 extension) When reaching memory, all extended ZEND_MINIT_FUNCTION will be executed.
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_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; }
##5. Compile and install the extension, restart php-fpm or mod_php5, etc.
6. Methods of using custom extensions in PHP
my_fwrite($fp, "aaTest"); var_dump($fp); my_fclose($fp); var_dump($fp);
7. We often use database connection resources and file handle resources in PHP, but they usually do not require us to release them manually, and there will be no memory leak problems. How is this achieved?
my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型
Then, if you need to implement the automatic release function, you only need to define the destructor and pass the function pointer.
Look at another question:
$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); }
Such as database connection, opening files, graphics canvas area, etc.
The resource type is actually just an integer, and the kernel can use this integer value to find the final required data in a place similar to a resource pool.
Example 1, example of file operation:
Code example:
<?php $file=fopen('a.txt','r');//使用fopen函数打开一个文件获取句柄。 fread($file,1024);//之后把该句柄传递给fread函数,即可对此文件进行后续操作。
Code example:
<?php $result=mysql_query('select * from tbale');//mysql_query函数执行一条sql,若失败,返回false;成功,查询结果被缓存,并返回资源标识(类似:Resource id#42)即指向该资源的句柄。 mysql_num_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询出来的条数 mysql_fetch_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询结构
You can use the is_resource() function to determine whether a variable is a resource, and the function get_resource_type() returns the type of the resource.
As for PHP resource variables, you don’t have to worry about issues like MYSQL connection not being released, because the destructor method is defined in the extension to help automatically release it.
Related recommendations:
PHP resource list, php resource_PHP tutorial
Summary of PHP resources, including: libraries, frameworks, templates, etc.
The above is the detailed content of PHP resource type example sharing. For more information, please follow other related articles on the PHP Chinese website!