为什么我的父进程在退出之前看不到孩子的输出? [英] Why doesn't my parent process see the child's output until it exits?
问题描述
考虑以下脚本:
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屋!