J'ai essayé d'écrire un scanner ping bare-bones en utilisant Perl pour un usage interne. Comme il analyse un réseau CIDR 24 bits, le script prend trop de temps à s'exécuter s'il s'exécute dans un seul thread. J'ai essayé d'ajouter une fonctionnalité de fork pour accélérer le processus, mais mon first attempt prenait à peu près le même temps car il n'y avait qu'un seul processus fils actif à la fois.Pourquoi mon programme Perl ne recueille-t-il pas les processus enfants après la fourchette?
Je lis sur les processus enfants dans le document perlipc et aussi dans le Perl Cookbook et est venu avec la deuxième version:
##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";
Lorsque je scanne mon réseau interne la sortie est:
$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
Comme on peut le voir dans le résultat, les threads qui réussissent un scan impriment le message «up», sortent proprement et sont récoltés par le processus parent. Les 251 autres threads quant à eux sont laissés pendants attachés à '/ sbin/init' comme le montre une liste rapide 'ps -ef'. Si j'ajoute un 'print' Enfant: $ currIP se terminant \ n "'dans le bloc de traitement enfant juste avant l'instruction exit, j'obtiens la sortie des 251 processus restants sur mon terminal" après "que mon script perl soit terminé.
Que se passe-t-il ici? Je pensais que le sous-programme $ SIG {CHLD} couplé à la boucle waitpid récolterait tous les processus fils et garantirait qu'aucun processus zombies/dangling ne soit laissé dans le système. En même temps, j'aimerais aussi pouvoir exécuter un nombre spécifique de processus fils à un moment donné, par exemple, 'n' enfants qui s'exécutent simultanément, chaque fois que l'un quitte le processus parent commence un autre enfant si nécessaire mais n'a pas plus de 'n' enfants à un moment donné. Est-ce possible? Si oui, pourrais-je obtenir un pseudo-code pour m'aider?
Quelle est la raison pour laquelle votre boucle passe de 1-254 (253?) Au lieu de 0-255? –
Matt Boehm 255 est généralement l'adresse de diffusion (en supposant un sous-réseau/24). 0 a aussi une signification particulière (en a/24), mais j'oublie ce que c'est. –
Matt, tous les 0 sont réservés pour l'ID réseau et tous les 1 pour l'adresse de diffusion. – aks