前面说了用Thread创建多线程,但是文章最后也说了该方法存在问题,那么,我们想起perl的另外一个好东西,fork,具体意思我就不多说了,就是用fork来模拟多线程,但是我再试验中发现一个问题,windows中规范一个进程可以fork的子进程最多为64个,那么如何突破这个限制呢?
父进程fork出的子进程在运行完后并不是完全销毁了,而是以僵死进程的形式存在,并且等待父进程的收割,那么如何收割呢,我查了下资料,说子进程终止会发送CHLD信号给父进程,我试验了下,发现在windows下该方法是行不通的,子进程终止后不会发送CHLD信号给父进程,那么我们只有另寻办法了。下面是我写的代码:
#!/usr/bin/perl -w
use IO::Socket;
use POSIX;
my @pids;
$ip=<>;
chomp($ip);
$minport=<>;
chomp($minport);
$maxport=<>;
chomp($maxport);
for(;$minport<=$maxport;$minport++){
if(@pids>50){
$p= waitpid(-1,0);
if($p>0){
@pids=grep {
$_ ne $p
} @pids;
}
}
$f=fork() ;
next unless defined $f;
if($f==0){
$s=IO::Socket::INET->new("$ip:$minport") ;
if($s){
print "$minport is open/n" ;
$s->close;
}else{
print "$minport is close/n" ;
}
exit 0;
} else{
push(@pids,$f);
}
}
代码中我定义了一个@pids的全局数组,该数组就是存储子进程pid的,当父进程检测子进程数目超过50时,便用waitpid等待任意一个子进程的停止并收割,这样会始终保持子进程数目在64以下,就不会有问题了。
我测试了下,在响应较快的服务器连接中不会有迟钝,但在响应慢的服务器上就会出现扫描50个端口后迟钝一会,才继续扫描,这是有待改善的。
文章有不妥之处,还望各位多多指教。