PHP资源类型
来源:互联网 发布:不可使知之 编辑:程序博客网 时间:2024/06/06 01:30
PHP资源类型
http://blog.csdn.net/a600423444/article/details/7566799
分类: Linux PHP C/C++2012-05-14 22:45 6693人阅读 评论(1) 收藏 举报
phpzenddescriptorfpfunctionlist
在PHP中,我们经常使用到资源类型变量。例如:mysql连接、文件句柄等。
这些变量无法使用标量来表示,那么在Zend内核中是如何将PHP中的资源变量与C语言中的资源衔接的呢?
一、资源变量在PHP中的使用
- $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中对应的资源。
- #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)会在PHP作为SAPI(例如,Apache的mod_php5扩展)被加载到内存时,会执行所有扩展的ZEND_MINIT_FUNCTION。
其中jinyong,是当前扩展的名字。例如此时扩展的名字就是jinyong
这里为了方便理解,我们就把它认为是扩展在初始化时,会向内核中注册新的资源类型。
四、创建资源变量
资源类型已经注册成功,也为资源定义了区分的类型名称。现在可以使用这种资源的变量了。
实现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中的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-fpm或mod_php5等
六、PHP中使用自定义扩展中的方法
- my_fwrite($fp, "aaTest");
- var_dump($fp);
- my_fclose($fp);
- var_dump($fp);
七、我们在PHP中经常使用数据库连接资源、文件句柄资源,但他们通常无需我们手工释放,也不会出现内存泄漏问题,这是如何实现的呢?
- my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型
那么,如果需要实现自动释放功能,只需要定义析构函数并传递函数指针即可。
再看一个问题:
- $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)中找到对应的指针,并进行相应操作。
- 而PHP资源变量,之所以不用担心类似MYSQL连接未释放问题,也是因为扩展中定义了析构方法,帮助自动释放。
0 0
- PHP资源类型
- PHP资源类型
- PHP资源类型
- PHP资源类型列表
- 16. PHP Resource 资源类型
- PHP中的资源类型
- PHP中的资源类型
- php 资源类型 fclose
- 资源类型
- 资源类型
- php学习笔记(十一)Resource 资源类型
- 构建一个资源类型的php扩展(二)
- 句柄和指针的区别(php资源类型)
- PHP中变量类型之特殊类型:资源类型、空类型
- 资源类型【Android】
- php中资源类型是个什么东西?谈下个人认识
- .Net嵌入资源类型
- VC++2005 StringTable资源类型
- 手机短号
- Hdoj 2333 Assemble 【二分】
- 关于逻辑的训练题
- linux下JAVA开发环境配置
- poj1721CARDS
- PHP资源类型
- 表达式树
- The 12th Zhejiang Provincial Collegiate Programming Contest - D
- 面向对象(子父类中构造函数的特点-子类实例化过程)
- 读书笔记---vi编辑命令解析
- HDU1425 sort【水题】
- java web.xml 基本配置了解(1)
- UINavigationController导航栏传值、改变颜色
- 解决问题:maven3.3.1 的-Dmaven.multiModuleProjectDirectory system propery is not set