fork()和STDOUT / STDERR到子进程的控制台 [英] fork() and STDOUT/STDERR to the console from child processes

查看:221
本文介绍了fork()和STDOUT / STDERR到子进程的控制台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个程序来分叉多个子进程,我想所有这些子进程能够写入 STDERR STDOUT ,输出没有乱码。我不会做任何花哨的,只是发出以一个新行结束的行(至少在我的理解是一个原子操作为Linux)。从perlfaq它说:

I'm writing a program that forks multiple child processes and I'd like for all of these child processes to be able to write lines to STDERR and STDOUT without the output being garbled. I'm not doing anything fancy, just emitting lines that end with a new line (that, at least in my understanding would be an atomic operation for Linux). From perlfaq it says:


主进程和后台进程(子进程)共​​享同一STDIN,STDOUT和STDERR文件句柄。如果两者同时尝试访问它们,奇怪的事情可能发生。你可能想关闭或重新打开这些为孩子。你可以通过打开一个管道(见打开)来解决这个问题,但在某些系统上,这意味着子进程不能超过父进程。

Both the main process and the backgrounded one (the "child" process) share the same STDIN, STDOUT and STDERR filehandles. If both try to access them at once, strange things can happen. You may want to close or reopen these for the child. You can get around this with opening a pipe (see open) but on some systems this means that the child process cannot outlive the parent.

它说我应该关闭或重新打开这些孩子的文件句柄。关闭很简单,但是重新打开是什么意思?我在我的子进程中尝试过这样的事情,它不工作(输出仍然是乱码):

It says I should "close or reopen" these filehandles for the child. Closing is simple, but what does it mean by "reopen"? I've tried something like this from within my child processes and it doesn't work (the output still gets garbled):

open(SAVED_STDERR, '>&', \*STDERR) or die "Could not create copy of STDERR: $!";
close(STDERR);

# re-open STDERR
open(STDERR, '>&SAVED_STDERR') or die "Could not re-open STDERR: $!";

那么,我做错了什么?它所暗示的管道示例会是什么样子?是否有更好的方法将多个进程的输出一起协调到控制台?

So, what am I doing wrong with this? What would the pipe example it alludes to look like? Is there a better way to coordinate output from multiple processes together to the console?

推荐答案

写入文件句柄< 为STDOUT和STDIN原子。对于像fifos这样的事情有特殊的情况,但这不是你目前的情况。

Writes to a filehandle are NOT atomic for STDOUT and STDIN. There are special cases for things like fifos but that's not your current situation.

当它说重新打开STDOUT这意味着是创建一个新的STDOUT实例这个新的实例不同于父的一个。这是如何可以有多个终端在您的系统上打开,而不是所有的STDOUT去同一个地方。

When it says re-open STDOUT what that means is "create a new STDOUT instance" This new instance isn't the same as the one from the parent. It's how you can have multiple terminals open on your system and not have all the STDOUT go to the same place.

管道解决方案将通过管道(如shell中的|)将子进程连接到父进程,并且您需要将父进程读出管道,复用输出本身。父节点负责从管道读取,并确保它不交错管道的输出和同时输出到父节点STDOUT的输出。有一个示例和写法此处管道。

The pipe solution would connect the child to the parent via a pipe (like | in the shell) and you'd need to have the parent read out of the pipe and multiplex the output itself. The parent would be responsible for reading from the pipe and ensuring that it doesn't interleave output from the pipe and output destined to the parent's STDOUT at the same time. There's an example and writeup here of pipes.

摘要:

use IO::Handle;

pipe(PARENTREAD, PARENTWRITE);
pipe(CHILDREAD, CHILDWRITE);

PARENTWRITE->autoflush(1);
CHILDWRITE->autoflush(1);

if ($child = fork) { # Parent code
   chomp($result = <PARENTREAD>);
   print "Got a value of $result from child\n";
   waitpid($child,0);
} else {
   print PARENTWRITE "FROM CHILD\n";
   exit;
}

看看孩子怎么不写到stdout,向父级发送消息,谁使用其stdout进行写入。一定要看看,因为我忽略了关闭不需要的文件句柄。

See how the child doesn't write to stdout but rather uses the pipe to send a message to the parent, who does the writing with its stdout. Be sure to take a look as I omitted things like closing unneeded file handles.

这篇关于fork()和STDOUT / STDERR到子进程的控制台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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