4

内部で使用するために、Perl を使用して最低限の ping スキャナーを作成しようとしています。24 ビットの CIDR ネットワークをスキャンするため、スクリプトをシングル スレッドで実行すると、実行に時間がかかりすぎます。プロセスを高速化するために fork 機能を追加しようとしましたが、一度にアクティブな子プロセスが 1 つしかなかったため、最初の試行にはほぼ同じ時間がかかりました。

私はperlipcドキュメントとPerl Cookbookで子プロセスを読み、2 番目のバージョンを思いつきました:

##Install the CHLD SIG handler
$SIG{CHLD} = \&REAPER;
sub REAPER {
    my $childPID;
    while (( $childPID = waitpid(-1, WNOHANG)) > 0) {
        print "$childPID exited\n";
    }
    $SIG{CHLD} = \&REAPER;
}

my $kidpid;
for (1 .. 254) {
    my $currIP = join ".", (@ipSubset[0,1,2], $_);

    die "Could not fork()\n" unless defined ($kidpid = fork);
    if ($kidpid) {
        #Parent process
        #Does nothing
    } 
    else {
        #Child process
        my $pingConn = Net::Ping->new();    #TCP
        say "$currIP up" if $pingConn->ping($currIP);
        $pingConn->close(); 

        #Nothing else to do
        exit;
    }
}

say "Finished scanning $ipRange/24";

内部ネットワークをスキャンすると、出力は次のようになります。

$perl pingrng2.pl 192.168.1.1
192.168.1.2 up
5380 exited
192.168.1.102 up
192.168.1.100 up
5478 exited
5480 exited
Finished scanning 192.168.1.1/24

結果からわかるように、スキャンに成功したスレッドは「up」メッセージを出力し、正常に終了して、親プロセスによってリープされます。一方、他の 251 のスレッドは、'/sbin/init' に接続されたままぶら下がったままになっています。exit ステートメントの直前の子処理ブロックに 'print "Child: $currIPending\n"' を追加すると、perl スクリプトが終了した「後」に、残りの 251 プロセスからの出力が端末に表示されます。

何が起きてる?$SIG{CHLD} サブルーチンと waitpid ループを組み合わせると、すべての子プロセスが取得され、システムにゾンビやダングリング プロセスが残らないようになると考えました。

同じ息で、特定の数の子プロセスをいつでも実行できるようにしたいと考えています。いつでも「n」人の子供よりも。これは可能ですか?はいの場合、私を導くのに役立つ疑似コードを入手できますか?

4

3 に答える 3

6

親プロセスが子プロセスより先に終了しているようです (したがって、子プロセスを取得する機会がありません)。代わりにこれを試してください:

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

use Net::Ping;

my @ipSubset = (192, 168, 10);

my $i = 0;
my @pids;
for my $octet (1 .. 254) {
    my $currIP = join ".", @ipSubset[0 .. 2], $octet;

    die "Could not fork()\n" unless defined (my $pid = fork);

    #parent saves chlidren's pids and loops again
    if ($pid) {
        push @pids, $pid;
        next;
    } 

    #child process
    my $pingConn = Net::Ping->new;
    say "$currIP up" if $pingConn->ping($currIP);
    $pingConn->close(); 
    exit;
}

#wait on the children
for my $pid (@pids) {
    waitpid $pid, 0;
}
于 2009-05-31T04:16:00.267 に答える
3

スレッドが ping() を呼び出すと、応答が設定されるまで IP への ping を試行し続けます。これを修正するには、ping() の 2 番目の引数としてタイムアウトを含めてみてください。現在、これらの残りのスレッドは、応答を取得するまで引き続き ping を実行しているようです。

設定された N 個のスレッドを持つ限り、0 ~ 255 をチャンクに分割しないのはなぜですか。簡単にするために、スレッド数に 2 の倍数を使用します。

于 2009-05-31T04:26:59.410 に答える