Perl-在fork/exec上传递一个开放的套接字

标签 perl sockets exec fork

我想要一个Perl守护程序来监听,并且接受从客户端传入的连接,然后派生 exec 另一个Perl程序来继续与客户端的对话。

我只是在进行 fork 时就可以做到这一点-守护程序代码中还包含 child 的代码。但是我看不到如何通过exec()将打开的套接字“传递”到另一个Perl程序。

不知何故,我觉得这在Unix(这是我的环境)中很容易,因此在Perl中也很容易。真的可以做到吗?

最佳答案

这可以通过大约三个步骤来完成:

  • 清除文件描述符上的close-on-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
    

    现在,您又在$fh中有了一个Perl级别的句柄。

    附录:正如池上在评论中提到的那样,您还可以确保套接字使用三个“标准”文件描述符(0(stdin),1(stdout),2(stderr))之一。 exec的默认值; 2。具有已知编号,因此无需传递任何内容; 3。perl将自动为它们创建相应的句柄。
    open STDIN, '+<&', $fh;  # now STDIN refers to the socket
    exec 'that_program';
    

    现在that_program可以简单地使用STDIN。即使输出也可以使用。文件描述符0、1、2没有固有的限制,它们只能用于输入或输出。只是所有Unix程序都遵循的约定。

    关于Perl-在fork/exec上传递一个开放的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14351147/

    相关文章:

    c - 我应该使用什么方法来知道在进程 fork 然后执行后打开了哪些 fds

    Perl 未初始化警告

    performance - 为了提高性能,建议安装 Perl 的方法是什么?

    perl - HTTP::Daemon:如何在 HTTP-Header 中为服务器设置自定义值?

    java - 如何检查当前是否在 Java 中连接了 Socket?

    python - 如何在 Python 中使用套接字创建 channel

    c - Language C - 获取流程所有者

    Java Runtime.getRuntime().exec - 没有这样的文件或目录

    perl - 哪些脚本语言很好地支持长(64 位)整数?

    c# - 异步客户端套接字未接收数据