在perl中是否可以建立一个管道,使父管道只有一个READER管道,而许多子管道在启动/退出时写入它?
典型的食谱代码是:
#!/usr/bin/perl -w
# pipe2 - use pipe and fork so child can send to parent
use IO::Handle;
pipe(READER, WRITER);
WRITER->autoflush(1);
if ($pid = fork) {
close WRITER;
chomp($line = <READER>);
print "Parent Pid $$ just read this: `$line'\n";
// do what you need
} else {
die "cannot fork: $!" unless defined $pid;
close READER;
print WRITER "Child Pid $$ is sending this\n";
close WRITER; # this will happen anyway
exit;
}
让我们假设一种情况,我需要我的父级“READER”从多个子级获取消息,是否可以在不保留管道列表(每个子级一个)的情况下执行此操作?我无法关闭父级中的 WRITER,因为下一个子级将无法获得有效的句柄进行写入。我还需要父级继续其常规操作,并且不阻止来自管道的任何客户端数据。
我需要的伪代码:
# parent code
pipe (READER, WRITER)
fork_random_number_of_children(READER,WRITER)
on_some_tick => {
my $data = read_from(READER, non_blocking)
if (data) print "Hey some child sent me: $data"
else print "No data, going back life"
do_other_things_before_next_tick()
}
child_job(R,W) { # lets assume this is called for each child fork
close (R); # no problem, its a copy
sleep (random duration)
print W, "Message from child with pid $$"
exit 0
}
最佳答案
我认为没有必要在父级中关闭WRITER
。这可能是一个很好的做法,但是由于关闭管道后您无法将同一个管道重新用于新的子进程,因此这是一个不这样做的好借口。如果在启动所有子进程之前保持 WRITER
打开,则可以将管道与多个子进程重用。这是概念证明:
use IO::Handle;
use POSIX ':sys_wait_h';
pipe(READER,WRITER);
WRITER->autoflush(1);
sub child_process {
my $stage = shift;
close READER; # also a best but optional practice
srand($$);
do {
sleep 1 + 5*rand();
print WRITER "Child Pid $$ ($stage) is sending this\n";
} while (rand > 0.5);
exit;
}
# initial set of children
for (my $i=0; $i<5; $i++) {
if (fork() == 0) {
child_process("LAUNCH");
}
}
# parent
my ($rin,$rout) = ('');
vec($rin,fileno(READER),1) = 1;
while (1) {
# non-blocking read on pipe
my $read_avail = select($rout=$rin, undef, undef, 0.0);
if ($read_avail < 0) {
if (!$!{EINTR}) {
warn "READ ERROR: $read_avail $!\n";
last;
}
} elsif ($read_avail > 0) {
chomp(my $line = <READER>);
print "Read in Parent $$: '$line'\n";
} else {
print STDERR "No input ... do other stuff\n";
# start some run-time child processes
if (time-$^T > 5 && time-$^T < 10) {
# launch a few more children in the middle of the program
if (fork() == 0) {
child_process("RUN");
}
}
sleep 1;
}
last if waitpid(-1,&WNOHANG) < 0; # no more children are alive
}
close WRITER; # now it is safe to do this ...
关于perl:一个 parent ,许多 child - parent 中的单管道阅读器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52723489/