我想要一个Perl守护程序监听,接受来自客户端的传入连接,然后 fork & exec 另一个Perl程序,用于继续与客户端进行对话。
我可以在简单分叉时做到这一点 - 守护程序代码也包含子代码。但我不知道打开的插座是如何通过"跨越exec()到另一个Perl程序。
不知怎的,我得到的印象是这在Unix(这是我的环境)中很容易,因此在Perl中也是如此。真的可以吗?
答案 0 :(得分:14)
这可以通过大约三个步骤完成:
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
现在,您再次在$fh
中拥有Perl级别的句柄。
附录:正如ikegami在评论中提到的,你也可以确保套接字使用三种“标准”文件描述符之一(0(stdin),1(stdout),2( stderr))1.默认情况下在execs中保持打开状态,2。已知数字,因此无需传递任何内容,并且3. perl将自动为它们创建相应的句柄。
open STDIN, '+<&', $fh; # now STDIN refers to the socket
exec 'that_program';
现在that_program
可以使用STDIN
。这甚至适用于输出;文件描述符0,1,2没有固有的限制,它们仅用于输入或输出。这只是所有unix程序遵循的惯例。