为什么我的父进程在退出之前看不到孩子的输出? [英] Why doesn't my parent process see the child's output until it exits?

查看:59
本文介绍了为什么我的父进程在退出之前看不到孩子的输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下脚本:

use IO::File;
$| = 1;
my ($handle, $pid) = myPipe();
if ($pid == 0) {
  print "$$";
  sleep 5;
  exit;
}

print "child: ".<$handle>."\n";

sub myPipe {
  my $handle = new IO::File();
  my $pid = open($handle, "-|");
  return ($handle, $pid);
}

在这种情况下,进程开始后5秒钟内不会出现"child:"消息.如果我从分叉的孩子中删除该睡眠呼叫,则它将立即打印.为什么分叉的孩子必须退出才能使管道冲刷到父级?

In this case, the "child:" message doesn't appear for 5 seconds after the process starts. If I remove the sleep call from the forked child, then it prints immediately. Why does the forked child have to exit for the pipe to flush to the parent?

推荐答案

有两个问题.首先,子进程正在缓冲其输出;其次,父进程正在使用<>运算符,该运算符将阻塞直到有整行可用或直到文件结束为止.

There are two issues. First, the child process is buffering its output; and second, the parent process is using the <> operator, which blocks until a complete line is available, or until end-of-file.

因此,获得期望结果的一种方法是让子进程在写入后立即关闭其输出流:

So, one way to get the result you were expecting is to have the child process close its output stream immediately after writing:

if ($pid == 0) {
    print "$$";
    close STDOUT;
    sleep 5;
    exit;
}

另一种方法是在子进程的输出中添加换行符,然后刷新流:

Another way is to add a newline to the child process's output, then flush the stream:

if ($pid == 0) {
    print "$$\n";
    STDOUT->flush;  # "close STDOUT;" will work too, of course
    sleep 5;
    exit;
}

刷新是必需的,因为(通常)管道是无缓冲的,而不是像通常连接到终端的流那样是行缓冲的.

The flush is necessary because pipes are (typically) unbuffered, rather than line-buffered as streams connected to the terminal usually are.

第三种选择是将子进程的输出流设置为自动刷新:

A third alternative is to set the child process's output stream to autoflush:

if ($pid == 0) {
    $| = 1;
    print "$$\n";
    sleep 5;
    exit;
}

这篇关于为什么我的父进程在退出之前看不到孩子的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆