2009-05-31 55 views
4

我一直在嘗試使用Perl編寫一個簡單的ping掃描器供內部使用。由於它掃描24位CIDR網絡,如果腳本運行在單個線程中,該腳本運行時間過長。我曾嘗試添加fork功能來加速此過程,但由於在任何給定時間只有一個子進程處於活動狀態,因此我的first attempt幾乎同時發生。爲什麼我的Perl程序在fork之後不會收穫子進程?

我的perlipc文件中以及在Perl Cookbook兒童進程讀取並與第二版本出來了:

##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'上,這可以通過一個快速的'ps -ef'列表來看到。如果我在退出語句之前在子處理塊中添加了'print'Child:$ currIP結尾\ n「',我的終端上剩餘的251個進程的輸出」在我的perl腳本退出後。

這是怎麼回事?我認爲與waitpid循環結合的$ SIG {CHLD}子例程將收穫所有的子進程,並確保系統中不存在殭屍/懸掛進程。

同樣我還希望能夠在任何給定的時間運行特定數量的子進程,比如說,'n'個併發運行的子進程,只要有一個退出父進程就會啓動另一個子進程但在任何特定時刻只有'n'個孩子。這可能嗎?如果是,我可以得到一些僞代碼來幫助指導我?

+0

爲什麼你的循環從1-254(253?)而不是0-255? – 2009-05-31 05:03:28

+0

Matt Boehm 255通常是廣播地址(假設是/ 24子網)。 0也有特殊含義(在/ 24),但我忘記它是什麼。 – 2009-05-31 05:59:08

回答

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; 
} 
3

當一個線程調用ping()時,它會一直嘗試ping IP直到它設置響應。要解決這個問題,請嘗試在ping()中包含超時作爲第二個參數。它看起來像現在,剩下的線程繼續ping響應,直到他們得到一個響應。

只要有一組N個線程,爲什麼不把0-255分成塊,例如有兩個線程,一個是從0-127變爲128-255?爲了簡單起見,我將使用2的倍數作爲線程數。

相關問題