【问题标题】:IPC between two Perl programs两个 Perl 程序之间的 IPC
【发布时间】:2019-11-15 17:32:51
【问题描述】:

我有一个 Perl 程序(这是父程序),它需要来自另一个 Perl 程序(子)的变量。我想通过 Linux 的管道机制来实现这一点。在网上搜索不成功后(众多示例中没有一个符合这个基本主题——我认为这个概念对于非专家来说是完全可以理解的,但我无法实现一个运行示例)。两个附加的程序显示了我对管道的理解,这可能是完全错误的,但我想学习它。为清楚起见:

Prog PARENT is running
    needs 2 variables from Prog CHILD
    PARENT calls CHILD (open CHILD ... ?)
    CHILD is running and can deliver the 2 variables
    CHILD opens PARENT, write/print the variables to PARENT
    CHILD closes PARENT
    CHILD exit
PARENT can now read from CHILD 

家长计划(呼叫者和接收者)

#!/usr/bin/env perl
use strict;
use warnings;
# file-name: mwe-ipc.pl
# this prog. is the PARENT
# Calls a CHILD by its prog.name

print "$0\n"; # show your progname
my $pid = open(CHILD, "mwe-ipc-child.pl |") or die "Couldn't fork: $!\n";
my @arr_receiver;
while (<CHILD>){
    # PARENT needs two variables from CHILD
    # how to get var1 and var2?
   @arr_receiver = $_;
}
close(CHILD);

print "arr_receiver[$_] = $arr_receiver[$_]\n" for (0..$#arr_receiver);

儿童计划(将被调用并回答)

#!/usr/bin/env perl
use strict;
use warnings;
# file-name: mwe-ipc-child.pl
# this prog. is the CHILD
# Called from a PARENT

print "$0\n";;
my $pid = open(PARENT, "| mwe-ipc.pl") or die "Couldn't fork: $!\n";
my $var1 = "a"; #"|l |p{2.7cm} |p{2cm}";
my $var2 = "b"; #"\textbf{G}& \textbf{Substantiv}& \textbf{Modus} \\";

while (<PARENT>){
   # PARENT needs two variables from CHILD
   # how to put var1 and var2?
   print PARENT $var1, $var2;
}
close(PARENT);

exit(0);

调用 PARENT Prog 输出 progname,然后是无限循环。 最终,来自 CHILD cmdline 的不必要调用提供了自己和父母的 progname。 有人可以帮忙吗?

【问题讨论】:

    标签: perl


    【解决方案1】:

    问题 1:基本原理

    让孩子执行父母是没有意义的。父级要捕获的输出应发送到 STDOUT。

    起始骨架如下所示:

    • 家长:

      #!/usr/bin/perl
      use strict;
      use warnings;
      
      use utf8;
      use open ':std', ':encoding(UTF-8)';
      
      open(my $CHILD, "-|", "mwe-ipc-child.pl")
         or die("Can't execute child: $!\n");
      
      my $response = do { local $/; <$CHILD> };
      close($CHILD);
      
      ... do something with response...
      
    • 孩子:

      #!/usr/bin/perl
      use strict;
      use warnings;
      
      use utf8;
      use open ':std', ':encoding(UTF-8)';
      
      my $response = ...;
      print($repsonse);
      

    问题 #2:协议

    您需要某种方式来判断一个值在哪里结束,另一个值在哪里开始。

    如果这些值永远不会包含换行符,您可以使用换行符将它们分开。

    • 孩子:

      print("$var1\n$var2\n");
      
    • 家长:

      chomp( my $var1 = <$CHILD> );
      chomp( my $var2 = <$CHILD> );
      

    否则,一个不错的可扩展方法是使用 JSON。

    • 孩子:

      use Cpanel::JSON::XS qw( encode_json );
      
      my $data = { var1 => $var1, var2 => $var2 };
      my $json = encode_json($data);
      binmode(STDOUT);
      print($json);
      
    • 家长:

      use Cpanel::JSON::XS qw( decode_json );
      
      open(my $CHILD, "-|:raw", "mwe-ipc-child.pl") or ...;
      my $json = do { local $/; <$CHILD> };
      close($CHILD);
      
      my $data = decode_json($json);
      my $var1 = $data->{var1};
      my $var2 = $data->{var2};
      

    【讨论】:

      【解决方案2】:

      非常非常感谢您的回答。您的解决方案按原样工作。但是对于那些和我同样感兴趣的人,我想展示对您的源代码的以下改编,它应该完全符合原始问题。从子级到父级交换变量。重要的附加知识在这里

      1) 做{local... in: https://www.perlmonks.org/?node_id=287647

      2) 不受缓冲区影响:Why doesn't my parent process see the child's output until it exits?

      父母:

      #!/usr/bin/env perl
      use strict;
      use warnings;
      # file-name: mwe-ipc.pl
      # this prog. is the PARENT
      # Calls a CHILD by its prog.name
      
      print "$0\n";
      use utf8;
      use open ':std', ':encoding(UTF-8)';
      
      open(my $CHILD, "-|", "mwe-ipc-child.pl") or die("Can't execute child: $!\n");
      
      # do { local $/; <$CHILD> }; this idiom is a consise way to slurp the entire 
      # contents of a file into a scalar without using a loop
      # $/ is the inut record separator(irs). In following manner the same as 
      # local $/ = undef. This eliminates the irs to nothing, which leads to a slurp 
      # instead of reacting upon \n, the default value, the new line sign. 
      # Local restricts that behaviour to the block {}.
      my $response = do { local $/; <$CHILD> };
      
      close($CHILD);
      
      #... do something with response...
      print "response from child is : $response \n";
      my @arr_response = split /\n/, $response;
      print "arr_response[$_] = $arr_response[$_]\n" for (0..$#arr_response);
      

      孩子:

      #!/usr/bin/env perl
      use strict;
      use warnings;
      # file-name: mwe-ipc-child.pl
      # this prog. is the CHILD
      # Called from a PARENT
      
      #print "$0\n"; # uncommented this print goes to the PARENT too.
      use open ':std', ':encoding(UTF-8)';
      my $var1 = "|l |p{2.7cm} |p{2cm}";
      my $var2 = "\\textbf{G}& \\textbf{Substantiv}& \\textbf{Modus} \\\\";
      my @response;
      
      print ($var1,"\n", $var2,"\n");
      

      “mwe-ipc.pl”的调用导致

      /home/hj/latex/mwes/ipc/mwe-ipc.pl
      response from child is : |l |p{2.7cm} |p{2cm}
      \textbf{G}& \textbf{Substantiv}& \textbf{Modus} \\
      

      arr_response[0] = |l |p{2.7cm} |p{2cm}
      arr_response[1] = \textbf{G}& \textbf{Substantiv}& \textbf{Modus} \\
      

      所以,正是我想要的,谢谢@ikegami

      【讨论】:

        猜你喜欢
        • 2017-06-06
        • 2015-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-02
        • 2016-03-22
        • 1970-01-01
        • 2021-07-28
        相关资源
        最近更新 更多