我正在尝试使用命名管道在
PHP中进行一些IPC.我有一个名为pipe的管道
$pipePath = __DIR__ . '/pipe';
posix_mkfifo($pipePath, 0600);
在完成一些计算之后,还有另一个进程应写入该管道.我可以等待它完成并用以下内容读取结果:
$result = file_get_contents($pipePath);
或者更冗长
$in = fopen($pipePath, 'r');
$result = fread($in, 8192);
fclose($in);
(我简化了第二种方法;在实际代码中我会检查错误,在循环中运行fread,以防结果为> 8192字节等)
但是,虽然其他进程应该完成,但我不相信它会成功,所以我想尝试读取结果时超时.在等待一段时间之后,我想放弃并报告错误,说它崩溃等等.给出两种方法,PHP代码将永远挂起(或者很长一段时间)等待写入管道的东西.具体来说,file_get_contents和fread将挂起.
我能想出的唯一解决方案是这样的:
$timeout = 10; //seconds
for ($i = 0; $i < $timeout; $i++) {
$in = @fopen($pipePath, 'rn');
if ($in) break;
sleep(1);
}
if (!$in) {
throw new RuntimeException("The other process did not finish in the allotted time");
}
$result = fread($in, 8192);
fclose($in);
这使用未记录的’n’标志来进行fopen,如this question中的一个注释所示.如果fopen调用阻塞,则会导致fopen调用立即失败.
但是,我不喜欢这个解决方案有两个原因:
>通过每秒检查一次管道,它做了不必要的工作.
>如果另一个过程中的计算需要1.01秒才能完成,这将等待整整2秒钟以获得结果.对于我想做的一些事情,这是浪费的时间,值得尝试解决问题.
当在URL上调用fopen时,我可以添加指定超时值的上下文参数.但是,这似乎不适用于此,也没有设置默认套接字超时.
用管道有更好的方法吗?如果没有,我可能会考虑切换到Unix套接字,但在其他过程中这些并不那么容易支持,所以我宁愿不这样做.
(仅供参考,我只关心Linux;如果这很重要,不需要在Windows或其他任何东西上运行.)