【问题标题】:Why we have not closed the descriptor pointing to a file?为什么我们还没有关闭指向文件的描述符?
【发布时间】:2014-01-22 12:18:04
【问题描述】:

我是 php 新手。当我阅读使用 proc_open() 从其官方文档中执行来自 php 的命令时,我发现了这个示例:

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);

$cwd = '/tmp';
$env = array('some_option' => 'aeiou');

$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);

if (is_resource($process)) {
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // Any error output will be appended to /tmp/error-output.txt

    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
}
?>

为什么我们没有使用 fclose() 关闭第三个(管道 [2])文件描述符,否则它会自动关闭?

我试图关闭它,但它给出了警告:

PHP Notice:  Undefined offset: 1 in test.php on line 121  
PHP Warning:  fclose() expects parameter 1 to be resource, null given in test.php on line 121

【问题讨论】:

  • 如果您使用文件路径和file 类型描述符,proc_open() 将处理此文件上的所有操作,因此您不会取回可以写入或读取的资源。

标签: php


【解决方案1】:

有趣的问题。您只能关闭 std* 管道。当您使用标准管道打开时:

$descriptorspec = array(
       0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
       1 => array("file", 'dump.log', "w"),  // file instead stdout
       2 => array("pipe", "a")
    );
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');

$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);

print_r($pipes);

你会看到类似的东西:

Array
(
    [0] => Resource id #5
    [2] => Resource id #6
)

所以 $pipes[1] 将不可用。

根据 php 源代码,它看起来只有“管道”落入 $pipes 数组。

对于管道:php 在 C 上使用“管道”调用。由于管道描述符在进程之间共享,操作系统只能在这种情况下关闭管道,如果没有进程正在使用管道。 “从技术角度来看,如果管道不必要的末端没有明确关闭,EOF 将永远不会返回。” - http://www.tldp.org/LDP/lpg/node11.html

【讨论】:

  • 我想问如果我们使用“fopen”打开一个文件然后我们使用“fclose”关闭它,但在这种情况下我们也在打开一个文件进行写入,为什么我们不关闭它, 或 php 自动关闭它?如果自动关闭它有什么特殊原因,为什么不自动关闭其他描述符,出于任何安全原因或其他原因?
  • 是的,php 会自动关闭“无管道”资源。关于管道 - 我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2018-04-15
相关资源
最近更新 更多