これは、およそ 3 つの手順で実行できます。
- ファイル記述子のclose-on-execフラグをクリアします。
- exec されたプログラムに、使用するファイル記述子を伝えます。
- ファイル記述子をハンドルに復元します。
1. Perl (デフォルト) は、開くファイル記述子に close-on-exec フラグを設定します。これは、ファイル記述子がexec
. 最初にこのフラグをクリアする必要があります:
use Fcntl;
my $flags = fcntl $fh, F_GETFD, 0 or die "fcntl F_GETFD: $!";
fcntl $fh, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!";
2.これで、ファイル記述子は で開いたままになるのでexec
、プログラムにそれがどの記述子であるかを伝える必要があります。
my $fd = fileno $fh;
exec 'that_program', $fd; # pass it on the command line
# (you could also pass it via %ENV or whatever)
3.反対側のファイルハンドルを復元します。
my $fd = $ARGV[0]; # or however you passed it
open my $fh, '+<&=', $fd; # fdopen
$fh->autoflush(1); # because "normal" sockets have that enabled by default
これで、再び Perl レベルのハンドルができまし$fh
た。
補遺:池上がコメントで述べたように、ソケットが3つの「標準」ファイル記述子(0(stdin)、1(stdout)、2(stderr))のいずれかを使用していることを確認することもできます。 2. 既知の番号を持っているので、何も渡す必要はありません。3. perl はそれらに対応するハンドルを自動的に作成します。
open STDIN, '+<&', $fh; # now STDIN refers to the socket
exec 'that_program';
that_program
を簡単に使用できるようになりましSTDIN
た。これは出力でも機能します。ファイル記述子 0、1、2 には、入力または出力専用であるという固有の制限はありません。これは、すべての UNIX プログラムが従う規則にすぎません。