资源类型
资源数据类型是PHP4引进的。资源是一种特殊的变量类型,保存了到外部资源的一个引用:如打开文件、数据库连接、图形画布区域等。
资源是通过专门的函数来建立,使用,关闭的,比如 fopen, socket_create, socket_accept等。
资源ID与fd
function fun2()
{
$fp1 = fopen("test.php", "rw");
var_dump($fp1);
$fp2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
var_dump($fp2);
sleep(30);
fclose($fp1);
socket_close($fp2);
sleep(3);
$fp3 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
var_dump($fp3);
sleep(30);
socket_close($fp3);
sleep(100);
}
保存为 test2.php
打印为:
resource(5) of type (stream)
resource(6) of type (Socket)
数字 5 和 6 表示在当前进程下PHP内核分配的编号,只要进程不结束,不管是什么类型的资源,这个编号都会一直增加。
内核中将注册的资源变量存储在一个HashTable中,并把资源所在HashTable中的key作为资源ID。所以,实际上PHP中的资源变量实际存储的是一个整型,通过这个ID找到HashTable中对应的资源。下面来看看此ID和系统资源是怎么匹配的。
ps -ef | grep test2
1575
cd /proc/1575/fd
ll
3 和 4 释放后,重新创建一个socket,重复使用了3,但是socket后面的编号是不一样的,意为指向不同的内核缓冲区地址,说明是不同的fd。
fd目录下为该进程打开的文件描述符,0,1,2 分别为自动打开的标准输入,标准输出,标准错误;3为打开文件,4为打开的socket,通常情况下PHP的资源ID是从4或5开始的,可见 resource_id 和实际的 fd_id 并没有什么关系,只是在HashTable里面将它们做了关联。
还有一点是,resource_id 是在进程内递增的,而 fd_id 在进程内是会被重复使用的,比如,如果 fd4 成功关闭,再新建一个 fd ,它的编号可能还是 4 。
释放资源
由于 PHP4 Zend 引擎引进了资源计数系统,可以自动检测到一个资源不再被引用了(和 Java 一样)。这种情况下此资源使用的所有外部资源都会被垃圾回收系统释放。因此,很少需要用某些 free-result 函数来手工释放内存。
注意: 持久数据库连接比较特殊,它们不会被垃圾回收系统破坏。