perl中可以分叉的进程数是否有限制?

时间:2012-04-11 18:25:23

标签: perl fork

我面临一个奇怪的问题。分叉进程的增长不超过64个。

sub create_process()
{
    my $child_pid;
    my @nsitr;

    my $i = 0;

    foreach my $domain (@domains)
    {
        @nsitr = @nameservers;
        open my $dnsfh, '>', $outputfile or die "Unable to open $outputfile - $!";
        foreach my $ns (@nameservers)
        {
            print "Forking child $i\n";
            defined($child_pid = fork() ) or (die "Unable to fork a new process" && next);
            $i++;
            if($child_pid == 0)
            {
                &resolve_dns($dnsfh, $domain, $ns);
                exit;
            }

        }
        close $dnsfh;
    }
}

输出

...
...
Forking child 60
Forking child 61
Forking child 62
Forking child 63
Forking child 64
Forking child 64
Forking child 64
Forking child 64
Forking child 64
...
...

3 个答案:

答案 0 :(得分:5)

Perl没有定义这样的限制,但大多数操作系统都这样做。使用waitpid来收集孩子,或者在类似Unix的系统上,您可以使用sigaction(来自POSIX模块)忽略SIGCHLD并使用SA_NOCLDWAIT标志让系统自动收获孩子。 (Linux恰好让你省略SA_NOCLDWAIT,但无论如何都应该使用它。)

答案 1 :(得分:2)

如果您想进行并行查找,可以使用Net::DNS附带的demo script或查看AnyEvent::DNS

后者提供

  

该模块提供了许多DNS便捷功能以及完全异步和高性能的纯perl存根解析器。

我没有使用它,但IO::Lambda::DNS也允许进行并行查询:

# parallel async queries
   lambda {
      for my $site ( map { "www.$_.com" } qw(google yahoo perl)) { 
         context $site, 'MX', timeout => 0.25; 
         dns { print shift-> string if ref($_[0]) }
      }
   }-> wait;

使用这些模块可能比手动管理叉子更可取。


根据你的评论,我想你可能误解了我想说的话。也许这会有所帮助:

#!/usr/bin/env perl

use strict; use warnings;

use AnyEvent::DNS;
use AnyEvent::Socket;
use YAML;

my %nameservers = (
    'Google' => '8.8.4.4',
    'Dnsadvantage' => '156.154.71.1',
    'OpenDNS' => '208.67.222.222',
    'Norton' => '198.153.194.1',
    'Verizon' => '4.2.2.4',
    'ScrubIt' => '207.225.209.66',
);

for my $ip ( values %nameservers ) {
    $ip = AnyEvent::DNS->new(
        server => [ parse_address($_) ],
        timeout => [3],
    );
}

my @domains = qw(example.com cnn.com bing.com);

my $cv = AnyEvent->condvar;
for my $domain (@domains) {
    for my $ns (keys %nameservers) {
        $cv->begin;
        $nameservers{$ns}->resolve(
            $domain, 'a', sub {
                $cv->end;
                print Dump { $ns => [ @{$_[0]}[0,4] ] };
            }
        );
    }
}

$cv->recv;

输出:

---
ScrubIt:
  - example.com
  - 192.0.43.10
---
ScrubIt:
  - cnn.com
  - 157.166.226.26
---
Norton:
  - example.com
  - 192.0.43.10
---
OpenDNS:
  - example.com
  - 192.0.43.10
---
Dnsadvantage:
  - example.com
  - 192.0.43.10
---
Verizon:
  - example.com
  - 192.0.43.10
---
Google:
  - example.com
  - 192.0.43.10
---
ScrubIt:
  - bing.com
  - 65.52.107.149
---
Norton:
  - cnn.com
  - 157.166.255.18
---
OpenDNS:
  - cnn.com
  - 157.166.255.19
---
Dnsadvantage:
  - cnn.com
  - 157.166.226.25
---
Verizon:
  - cnn.com
  - 157.166.226.26
---
Google:
  - cnn.com
  - 157.166.255.18
---
Norton:
  - bing.com
  - 65.52.107.149
---
OpenDNS:
  - bing.com
  - 65.52.107.149
---
Dnsadvantage:
  - bing.com
  - 65.52.107.149
---
Verizon:
  - bing.com
  - 65.52.107.149
---
Google:
  - bing.com
  - 65.52.107.149

答案 2 :(得分:0)

如果你使用某种Unix系统,你可能需要use threads模块而不是forks。实际上它在某些方面甚至更重,可能需要一些额外的内务处理,但这可能会超过分叉过程限制。可能存在其他限制,这些限制会阻止您创建大量线程。