#!/usr/bin/perl use strict; use IO::Select; use POSIX qw(WNOHANG);
#---Define constants:定义准备先fork几个Process use constant PREFORK_CHILDREN => 3; # debugging information:显示过程 use constant DEBUG => 1;
# declare globals my $DONE=0; # set flag to true when server done my %STATUS = (); #child status information, child pid form keys of the ha sh, status form the values #--- 纪录所有Child Process的id... my %CHILDREN = (); #---Interrupt handles,跳出loop $SIG{TERM} = $SIG{INT}=$SIG{HUP} = sub { $DONE++ }; #--- get CHLD Signal $SIG{CHLD} = sub { while((my $child=waitpid(-1,WNOHANG)) > 0){ delete $CHILDREN{$child}; } }; # create a pipe for IPC:建立PIPE pipe(CHILD_READ,CHILD_WRITE) or die "Can't make pipe!/n"; my $IN = IO::Select->new(/*CHILD_READ); # prefork some children make_new_child() for (1..PREFORK_CHILDREN);
# main loop while(!$DONE){ # avoid parent block in the I/O call if ($IN->can_read){ # got a message from one of the children my $message; next unless sysread(CHILD_READ,$message,4096); # may contain several messages my @messages = split "/n",$message; # retrive every pid and status code foreach (@messages){ next unless my ($pid,$status) = /^(/d+) (.+)$/; # change status if($status ne "done"){ $STATUS{$pid} = $status; }else{ # delete pid delete $STATUS{$pid}; } } }
warn join(' ',map {"$_=>$STATUS{$_}"} keys %STATUS),"/n" if DEBUG; last unless %CHILDREN } warn "Termination received, killing children/n" if DEBUG; #-------------杀掉所有Child Process kill TERM => keys %CHILDREN; sleep while %CHILDREN;
warn "Normal termination./n"; exit 0; #---- 建立新的Process sub make_new_child{ die "can't fork :$!" unless(defined( my $child = fork())); if($child){ # child > 0, so we're the parent $CHILDREN{$child} = 1; warn "launching child $child/n" if DEBUG; }else{ close CHILD_READ; # no need to read from pipe do_child(); # child handles incoming connections exit 0; # child is done } } #------ child process sub do_child{ # write status code: idle syswrite CHILD_WRITE,"$$ idle/n"; for(1..1000000){ }; syswrite CHILD_WRITE,"$$ busy/n"; for(1..1000000){ }; syswrite CHILD_WRITE,"$$ done/n"; } |