我正在尝试使用命名管道在PHP中进行一些IPC。我有一个通过创建的命名管道
$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
fopen
但是,由于两个原因,我不喜欢此解决方案:
在fopen
URL上调用时,我可以添加上下文参数来指定超时值。但是,这似乎不起作用,也没有设置默认的套接字超时。
有没有更好的方法用管道来做到这一点?如果没有,我可能会考虑切换到Unix套接字,但是在其他进程中不那么容易支持它们,因此我宁愿不这样做。
(仅供参考,我只关心Linux;如果这很重要,则不需要在Windows或其他任何工具上都可以使用的东西。)
我找到了一种方法来做...
首先,我不知道该n
标志,这是非常有用的信息!
但是,如果函数阻塞将失败,这并非完全正确。它仍然返回文件句柄。我们可以使用文件句柄并将其传递给stream_select
函数,以等待数据可用。
像这样:
$f=fopen("my.fifo","rn");
$r=array($f);
$w=array();
$x=array();
stream_select($r,$w,$x,10);
此代码等待10秒,以便其他人向fifo的另一端写入内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句