我正在尝试构建一个程序,它创建一些forks并将fork的结果写回主程序。因此我尝试使用IO::Pipe
sub ForkRequests {
my $pipe = IO::Pipe->new();
my $pid;
foreach my $feature ( @features ) {
if ( $pid = fork() ) {
$pipe->reader();
while ( <$pipe> ) {
print $_. "\n";
}
}
elsif ( defined $pid ) {
#child
$pipe->writer();
#somecalculations [...]
print $pipe $calcresults;
}
}
}
我从模块的文档中获取了管道的代码。
如果我现在尝试执行,我会收到一条错误消息
Can't locate object method "reader" via package "IO::Pipe::End" at lmtest3.pl line 56.
Can't locate object method "writer" via package "IO::Pipe::End" at lmtest3.pl line 63.
Can't locate object method "reader" via package "IO::Pipe::End" at lmtest3.pl line 56, <GEN0> line 1.
Can't locate object method "writer" via package "IO::Pipe::End" at lmtest3.pl line 63, <GEN0> line 1.
因此,我的代码似乎不会启动管道对象,而是IO::Pipe::End
。
所以我的问题是,有人能看到那里的错误吗?为什么它会返回错误的对象,以及如何正确完成?
修改
我对某些服务器有一些请求(大多数时候1请求7个错误)。
这些请求名称保存在@features
中,并将在#somecalculations
处执行。
因为服务器响应很慢,我希望这些请求并行启动。他们都必须回到主程序并将回复打印到控制台。
我试过这段代码
sub ForkRequests {
my $i = 0;
my @pipes;
my $pid;
foreach my $feature ( @features ) {
@pipes[$i] = IO::Pipe->new();
if ( $pid = fork() ) {
@pipes[$i]->reader();
}
elsif ( defined $pid ) {
#child
@pipes[$i]->writer();
# calculations
my $w = @pipes[$i];
print $w $calc;
print $w "end\n";
}
$i++;
}
}
if ( $pid == 1 ) {
while ( 1 ) {
foreach my $pipe ( @pipes ) {
while ( <$pipe> ) {
unless ( $_ == "end" ) {
print $_. "\n";
}
else { last; }
}
}
}
}
else {
exit;
}
}
如上所述,为了保存这些管道,但我仍然在阅读它们时遇到问题,因为程序会在得到答案之前退出。
答案 0 :(得分:3)
问题在于您要求多个子进程,但尝试对所有子进程使用相同的管道。
reader
方法将$pipe
转换为可以从中读取数据的IO::Pipe::End
对象,因此第一个子项正确连接。但是,然后再次在reader
上调用$pipe
,并抛出错误,因为它不再是正确类的对象。
您只需为每个子进程创建一个新管道:
sub fork_requests {
for my $feature ( @features ) {
my $pipe = IO::Pipe->new;
my $pid;
if ( $pid = fork ) {
$pipe->reader;
print while <$pipe>;
}
elsif ( defined $pid ) {
$pipe->writer;
# some calculations . . .
print $pipe $calcresults;
exit;
}
}
}
<强>更新强>
好吧,我想我明白你需要什么。这个完整的程序应该告诉你。
我已经编写了fork_requests
,因此它需要一个功能列表作为参数,并且我编写了子代码,以便它休眠两秒钟来模拟处理时间,然后只需打印功能的名称
如我所建议的那样,父代码将所有管道存储在一个数组中,并按照它们排队的顺序打印每个管道的输出。所有五个子进程在两秒后完成,因此父进程暂停,然后打印最初传入的功能。
use strict;
use warnings;
use IO::Pipe;
STDOUT->autoflush;
fork_requests('A' .. 'E');
sub fork_requests {
my @pipes;
for my $feature ( @_ ) {
my $pipe = IO::Pipe->new;
my $pid;
if ( $pid = fork ) {
$pipe->reader;
push @pipes, $pipe;
}
elsif ( defined $pid ) {
$pipe->writer;
select $pipe;
# some calculations . . .
sleep 2;
my $calcresults = $feature;
print $calcresults, "\n";
exit;
}
}
for my $pipe ( @pipes ) {
print while <$pipe>;
}
}
<强>输出强>
A
B
C
D
E