Я пытался написать простой пинг-сканер, используя Perl для внутреннего использования. Поскольку он сканирует 24-битную сеть CIDR, выполнение сценария занимает слишком много времени, если он выполняется в одном потоке. Я попытался добавить функциональность форка, чтобы ускорить процесс, но моя первая попытка заняла почти столько же времени, поскольку в каждый момент времени был активен только один дочерний процесс.
Я прочитал о дочерних процессах в документе 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
Как можно видеть в результате, потоки, которые выполняют успешное сканирование, печатают сообщение «вверх», выходят корректно и получают исходный процесс. Тем временем остальные 251 поток остаются привязанными к / sbin / init, как видно из быстрого списка ps -ef. Если я добавлю «print: Child: $ currIP end \ n» в дочерний блок обработки непосредственно перед оператором выхода, я получу вывод из оставшихся 251 процессов на моем терминале «после» завершения моего perl-скрипта.
Что здесь происходит? Я думал, что подпрограмма $ SIG {CHLD} в сочетании с циклом waitpid пожнет все дочерние процессы и гарантирует, что в системе не останется ни одного зомби / висячих процессов.
В то же время я также хотел бы иметь возможность запускать определенное количество дочерних процессов в любой момент времени, например, 'n' дочерние процессы, запущенные одновременно, каждый раз, когда выходит из родительского процесса, запускается другой дочерний процесс, если необходимо, но не имеет больше чем n детей в любой момент. Это возможно? Если да, могу ли я получить какой-нибудь псевдокод, который поможет мне?