3

最近,当我想在两个进程之间进行通信时,我在使用 (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);
     }
}

在这个样本中another_process_packetprocess_packet. 我这样写代码的原因是,我想使用来自套接字的相同数据并实际获取一次。

提前致谢。

4

3 回答 3

6

您当然可以在父进程中缓冲,并且仅在子进程的fd可写时才写入子进程(即写入不会阻塞)。您可以使用正确的 args 自己执行此操作以进行 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 $_"慢孩子。)如果可能,在 while 循环期间继续写入,但不要阻塞循环。最后,您实际上会阻塞,直到所有写入完成。

我的测试脚本在 gist.github:http ://gist.github.com/126488

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

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

于 2009-06-09T13:18:30.533 回答
1

大小在内核中设置。您可以使用更高的限制重新编译内核或使用中间缓冲进程

于 2009-06-09T10:09:26.517 回答
0

进程句柄包含一个名为“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);
     }
}
于 2009-06-16T01:41:26.167 回答