PHP可以返回ID为#0的资源吗?

时间:2011-08-04 15:34:06

标签: php resources

我想知道有效的PHP资源是否有可能ID为0.我正在获取数据库连接资源,到目前为止它们都是非零正整数。只是好奇资源的潜在ID范围是什么。

2 个答案:

答案 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开始