“运行”;减去;来自perl管道

“运行”;减去;来自perl管道,perl,exec,fork,pipe,dup,Perl,Exec,Fork,Pipe,Dup,我正试图从Perl中设置任意管道,其方式与shell可能的方式大致相同 这具有预期的效果,就像“echo foo | sed s/oo/ar/”: 但是,当我将第二个参数设置为“less”时,我的终端会闪烁,并且在寻呼机中看不到输出。除了短暂的闪光之外,没有任何迹象表明跑步会减少 现在我一点也不明白的是,下面的行为确实像“echo foo | less”: 但我一点也不明白对pipe()的调用在做什么。第一个论点应该是“读者”,第二个论点应该是“作者”。斯丁是如何成为“作家”的 我对这一切感到非

我正试图从Perl中设置任意管道,其方式与shell可能的方式大致相同

这具有预期的效果,就像“echo foo | sed s/oo/ar/”:

但是,当我将第二个参数设置为“less”时,我的终端会闪烁,并且在寻呼机中看不到输出。除了短暂的闪光之外,没有任何迹象表明跑步会减少

现在我一点也不明白的是,下面的行为确实像“echo foo | less”:

但我一点也不明白对pipe()的调用在做什么。第一个论点应该是“读者”,第二个论点应该是“作者”。斯丁是如何成为“作家”的


我对这一切感到非常困惑,并且认为底层Unix API可能有一些基本的东西我遗漏了或忘记了。

这是一个有趣的时间问题:

  • Shell分叉,创建一个进程组,将终端前台组设置为它,并执行
    perl
  • perl
    forks和execs
    less
  • perl
    execs
    echo
  • echo
    退出后,shell相信任务已完成,并再次将自己设置为终端前台进程组
  • less
    尝试获取终端。它不在终端前台进程组中<代码>更少失败
最简单的解决方案:将
fork
更改为
!fork
(或者等效地,交换
if
else
块)。这样,管道的最后阶段定义了作业的生命周期。(如果您仔细观察,shell在运行管道时也会以相同的顺序分叉和执行进程。)

#!/usr/bin/perl
use strict;

use IO::Handle;

$| = 1;

my ($first_prog, $second_prog) = ([qw(echo foo)], [qw(sed s/oo/ar/)]);
#$second_prog = ["less"];

pipe(my $second_prog_input, my $first_prog_output)   
    or die "problem setting up pipe: $!\n";

if (fork) {
    STDOUT->fdopen(fileno($first_prog_output), 'w') or die;
    exec(@$first_prog) or die;
}
else {
    STDIN->fdopen(fileno($second_prog_input), 'r') or die;
    exec(@$second_prog) or
      die "couldn't exec: $!: command was @$first_prog\n";
}
pipe(my $first_prog_output, STDIN) or die "problem setting up pipe: $!\n";

my ($first_prog, $second_prog) = ([qw(echo foo)], ["less"]);

open($first_prog_output, "-|", @$first_prog) or
  die "$!: command was @$first_prog\n";

exec(@$second_prog) or
  die "couldn't exec: $!: command was @$first_prog\n";