PHPで任意のファイルデスクリプタを開く

PHP には fdopen がないので、子プロセスについては /dev/fd/<FD番号> で代用してます。
PHP の機能ではありませんが。。

<?php
// child.php: 子プロセス(parent.php から実行される)
$fd = 4; // 親プロセスとのやり取りに使うファイルデスクリプタ(0:stdin, 1:stdout, 2:stderr)
$fdfile = “/dev/fd/$fd”;
if(!file_exists($fdfile)){
   die(“ファイルデスクリプタが開かれていません”);
}
 
$pipe = fopen($fdfile, “r”);
while(!feof($pipe)){
  echo fread($pipe, 1024);
}
fclose($pipe);

 

<?php
// parent.php: 親プロセス
$fd = 4; // 子プロセスとの通信に使うファイルデスクリプタ
$fp = proc_open(“php child.php”, array(
  $fd=>array(‘pipe’, r),
),$pipes);
 
fwrite($pipes[$fd], “Hello world!!”);
fclose($pipes[$fd]);
 
proc_close($fp);

 
FreeBSD の場合、標準では /dev/fd に 0,1,2 しかないため動作しません。
次のようにしてfdescfs を /dev/fd にマウントすればプロセスごとのファイルデスクリプタを自動作成してくれるようになります。

# echo “fdescfs /dev/fd fdescfs rw 0 0” >> /etc/fstab
# mount /dev/fd

または /dev/fd を使わない実装に置き換える事でも動作します。
この場合、ファイルデスクリプタが開いているかの確認には fstat [-p PID] を使うといいかもしれません。

// child.php: FreeBSD で devfs を使っている場合の代替実装。
$fd = 4;
$pipe = popen(‘cat < &'.$fd, 'r');
echo fread($pipe, 1024)
pclose();