文件描述符 4 和 5 发生了什么?

What happened to file descriptor 4 and 5?

如果您从 CLI 使用 PHP 打开文件并检索文件描述符:

$fp = fopen("somefile", "r"); 
echo 0 + $fp; 

你得到了令人惊讶的结果 5。运行 来自 Apache mod_php 你得到了预期的 3。我知道 0 是 STDIN,1 是 STDOUT, 2 是 STDERR,但是当我尝试打开 php://fd/3php://fd/4 时,我收到一条错误消息,提示它们不存在。

无论我尝试磁盘上的文件还是 php://memory 而不是 somefile,结果都不会改变。如果我使用 php -rphp x.php.

它也不会改变

那么文件描述符 3 和 4 发生了什么?那里是否潜伏着一些我不知道的有趣功能,一些仅在某些情况下存在的流包装器?

没有。它是文件描述符 3,正如您所想的那样。

strace -etrace=open php -r '$fp = fopen("somefile", "r"); echo 0 + $fp;'
[…]
open("/home/username/somefile", O_RDONLY)   = 3
5+++ exited with 0 +++

将 PHP 资源(例如文件句柄)强制转换为整数会为您提供其 PHP 资源标识符,而不是其文件描述符。资源号是从1开始分配的,不是0;当 CLI 中的 运行 时,前三个总是分配给 STDINSTDOUTSTDERR 流。虽然与文件描述符有一些对应关系,但这是巧合,并且当您开始考虑非文件资源时就会崩溃,例如 MySQL 结果或不受文件句柄支持的流(如内存或复杂包装器) .

(我不确定第四个资源在 CLI 下的用途是什么。无法通过 ID 获取资源,因此很难发现它是什么。)