我想知道有效的PHP资源是否有可能ID为0.我正在获取数据库连接资源,到目前为止它们都是非零正整数。只是好奇资源的潜在ID范围是什么。
答案 0 :(得分:4)
资源ID可以在int
的范围内。通过终端在PHP的源代码目录中搜索“resource”或“ZEND_FETCH_RESOURCE”。然后你会看到这个功能:
(档案./Zend/zend_list.c
,第110行)
ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id,
char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
在函数内部,您会看到passed_id
是资源的ID,而且类型为int
。
通常,库会传递默认ID -1
,例如在文件./ext/mysql/php_mysql.c
中,第1060行。
通常,您可以假设所有库都将传递值大于0的实/存在资源ID,但这不是每个库必须遵循的规则 - 可以传递否定资源ID或0。
答案 1 :(得分:3)
似乎没有...我找不到确切的原因,但这是我尝试过的(也许其他人可以为zend引擎更多地了解这种行为)
1.-在C中,我编写了一个非常愚蠢的程序,它生成了一个文件描述符#0(这与php中的资源不同,但我用文件资源尝试了这个,所以我们可以以某种方式将两种语言联系起来)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int
main(int argc, char *argv[])
{
int a;
char buff[8];
close(0);
close(1);
close(2);
a = open("./output", O_CREAT | O_TRUNC | O_WRONLY);
sprintf(buff, "%d\n", a);
write(a, buff, strlen(buff));
close(a);
}
此代码将关闭文件描述符0,1,2。打开一个新文件并保存描述符,结果如下:
$ cat output
0
$
现在,在php:
<?php
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$asd = fopen('./outputphp', 'w');
fwrite($asd, print_r($asd, true));
fclose($asd);
这将输出:
$ cat outputphp
资源ID#5
$
所以即使关闭stdin,stdout和stderr,php也不会重用资源ID。更重要的是,stdin id为#1,stdout为#2,而stderr为#3,实际上stdin有文件描述符0,stdout有1,而stderr有2.还有另外一个id#4已经分配。
所以我要说php保留id#0或根本不使用它。
greping通过zend引擎代码,我发现实际上资源#0用于在ZTS(启用线程安全性)时在sapi(cgi,cli,modules等)中初始化zend引擎的所有代码。像:
tsrm_startup(1, 1, 0, NULL);
tsrm_ls = ts_resource(0);
清理zend引擎时,它将从id#0开始遍历资源表。你不能(至少我不能)在启用或不启用线程安全的情况下获得资源#0,因此#0似乎是为两种情况保留的,但仅在启用ts时使用。
编辑:总结;)似乎你不能拥有小于1的资源ID,默认情况下打开1,2,3(不确定#4,但可能会打开任何新资源)从#4或#5开始