четверг, 31 мая 2012 г.

Многопоточность в Perl. Threads, Queue.

У меня уже был пост об этом. Со временем исправил много багов. Теперь нити работают через очередь, не зависают. Данный скрипт пингает хосты из сети, которую мы ему задаем в переменной $network, выдаёт статистику "сколько хостов ответило из общего количества в сети". Сеть задаём в формате N.N.N.N/N, модуль Net::Netmask определяет кол-во хостов в сети. В данном случае стартует 25 нитей, каждая из которых выполняет функцию ping. Когда очередь исчерпана, скрипт переходит к подсчёту статистики из файла.


#!/usr/bin/perl -w
#Ping network with threads and queue

use threads;
use Net::Ping;
use Net::Netmask;
use Thread::Queue;

# Programm variables

$debug=1;
$data_queue0 = Thread::Queue->new;
my $sleeptime = 0;                              

$network='178.76.215.0/25';

sub cidr {
  my $net = shift @_;
  my $block = Net::Netmask->new($net);
  my @pool;
  $size=$block->size();

  for (my $i=0; $i<=$size; $i++) {
   #print $block->nth($i),"\n";
 push (@pool, $block->nth($i));
 
  }
  return @pool;

}
                                                        
sub ping {
  while ($data_queue0->pending()) {
  my $host = $data_queue0->dequeue;
  my $pingprotocol = "icmp";
  my $pingtimeout = 1;
  my $pinglength = 1;
                                                                                                 
  my $p = Net::Ping->new($pingprotocol,$pingtimeout,$pinglength);
    if ( $p->ping($host) ) {
      print OFILE "$host OK\n";
      #print "$host OK\n";
        }  
  $p->close();
  }
}


sub que {
    print "Starting que sub\n";
    my @ar=@_;
    #print @ar,"\n"; 
    my $a;

    foreach my $ip (@ar) {
     $data_queue0->enqueue($ip);
  $a++;
    }

    if ($debug==1) { print "$a elements queued\n"; }
}

sub startthreads {
    for ($m=0; $m<=24; $m++) {
 sleep($sleeptime);
 $thrd[$m] = threads->new(\&ping, $data_queue0);
     print "Thread $m started.\n";  

    }
    print "All threads are started\n";                                            
    foreach (@thrd) { $_->join(); }
    print "All threads are joined!\n";
}

#Programm body

#1 - Recive data from cidr to array
@ipaddr = cidr($network);

#2 - Insert array into queue
que(@ipaddr);

#3 - Open file for inserting stdout from threads
open OFILE, ">ping_network_stats.txt";

#4 - Create threads
startthreads;

#5 - Close file with WRITE ONLY
close(OFILE);

#6 - Open file with READ ONLY
open OFILE1, ";

#8 Delete empty strings
chomp @count;

#9 - Print results of programm 
print "Network usage\: ",$#count," of ",$size,", ", $use=($#count/$size)*100, " %";

#10 - Close file descriptor with WRITE ONLY
close (OFILE1);

Комментариев нет:

Отправить комментарий