Perl 我如何防止家长在给孩子写信时阻塞?

Perl 我如何防止家长在给孩子写信时阻塞?,perl,ipc,interprocess,Perl,Ipc,Interprocess,最近,当我想在两个进程之间进行通信时,我在使用(pipe |-)时遇到了一个问题。 基本上,子进程处理STDIN的速度不如父进程快。这导致父级等待STDIN空闲,并使其运行缓慢 STDIN可以有多大,是否可以修改它。如果是,最佳实践规模是多少 下面是一些代码示例来说明我的意思: if ($child_pid = open($child, "|-")) { $child->autoflush(1); # PARENT process while (1) {

最近,当我想在两个进程之间进行通信时,我在使用(pipe |-)时遇到了一个问题。 基本上,子进程处理STDIN的速度不如父进程快。这导致父级等待STDIN空闲,并使其运行缓慢

STDIN可以有多大,是否可以修改它。如果是,最佳实践规模是多少

下面是一些代码示例来说明我的意思:

if ($child_pid = open($child, "|-"))
{
    $child->autoflush(1);

    # PARENT process
    while (1)
    {

             # Read packet from socket save in $packet
             process_packet($packet);

             # forward packet to child
             print $child $packet;
     }
}
else
{
     die "Cannot fork: $!" unless defined $child_pid;
     # CHILD process
     my $line;  

     while($line = <STDIN>)
     {
         chomp $line;
         another_process_packet($line);
     }
}
if($child\u pid=open($child,“|-”)
{
$child->autoflush(1);
#父进程
而(1)
{
#从套接字读取数据包,保存在$packet中
处理数据包($packet);
#将数据包转发给子级
打印$child$数据包;
}
}
其他的
{
除非定义了$child\u pid,否则模具“不能分叉:$!”;
#子进程
我的美元线;
而($line=)
{
chomp$行;
另一个处理包($line);
}
}
在此示例中,
另一个\u处理\u数据包
处理\u数据包
慢。我这样写代码的原因是,我想使用来自套接字的相同数据,并实际获取一次


提前感谢。

大小在内核中设置。您可以使用更高的限制或使用。

当然,您可以在父进程中使用缓冲区,并且仅在子进程的fd可写时(即,写入不会阻塞)才向子进程写入。您可以使用syswrite的正确参数自己执行此操作,或者使用事件循环:

use AnyEvent;
use AnyEvent::Handle;

# make child, assume you write to it via $fh

my $done = AnyEvent->condvar;
my $h = AnyEvent::Handle->new( fh => $fh );

while( you do stuff ){
    my $data = ...;
    $h->push_write($data); # this will never block
}

$h->on_drain(sub { $done->send });
$done->wait; # now you block, waiting for all writes to actually complete
编辑:这以前是未经测试的,但我测试了它,它可以工作。(我使用了
perl-ne“sleep 1;print$\ucode>作为慢子级。)如果可能的话,写入将在while循环期间继续,但决不会阻塞循环。最后,实际上是阻塞,直到所有写入都完成

我的测试脚本位于gist.github上:

您可以看到子循环如何阻塞阻塞循环,但它如何不阻塞非阻塞循环。当你这么说的时候,很明显;)


(最后,作为一般的经验法则,如果您正在与网络或其他进程交互,则可能应该使用事件循环。)

进程句柄包含一个名为“blocking”的成员函数。只需将阻塞设置为0,父进程就不会被阻塞

if ($child_pid = open($child, "|-"))
{
    $child->blocking(0);    # Key to the solution.
    $child->autoflush(1);

    # PARENT process
    while (1)
    {

             # Read packet from socket save in $packet
             process_packet($packet);

             # forward packet to child
             print $child $packet;
     }
}
else
{
     die "Cannot fork: $!" unless defined $child_pid;
     # CHILD process
     my $line;  

     while($line = <STDIN>)
     {
         chomp $line;
         another_process_packet($line);
     }
}
if($child\u pid=open($child,“|-”)
{
$child->blocking(0)#是解决方案的关键。
$child->autoflush(1);
#父进程
而(1)
{
#从套接字读取数据包,保存在$packet中
处理数据包($packet);
#将数据包转发给子级
打印$child$数据包;
}
}
其他的
{
除非定义了$child\u pid,否则模具“不能分叉:$!”;
#子进程
我的美元线;
而($line=)
{
chomp$行;
另一个处理包($line);
}
}

您能发布制作人和消费者脚本的简短版本吗?brain d foy,谢谢您的更改。虽然有这么多的错误让人有点尴尬…顺便说一句,谢谢,但我不想因为任何原因阻止家长。也许我需要更多地了解任何事件。谢谢,那就别挡了。我只在最后阻塞,因为进程即将退出,如果您带着未写入的数据退出,孩子将永远看不到它。如果这是一个长时间运行的进程,您就不需要阻塞。好吧,似乎AnyEvent::Handle工作得很好,但我仍然有一些问题。在我停止子进程一段时间以使STDIN缓冲区满后,父进程将数据推送到wbuf,这就是它应该做的,但事情是在我释放子进程之后,子进程只处理它保存在STDIN缓冲区中的数据,而从不触摸wbuf。然后,为了迫使wbuf将其数据推送到STDIN中,我使用on_drain(sub{$done->send})和在使用$done->recv之后的一行让父级等待,但在这一刻,我丢失了一些来自套接字的数据。你知道我怎么处理这个问题吗???