现在的位置: 首页 > 综合 > 正文

父进程与子进程communicate..利用PIPE的例子

2013年03月04日 ⁄ 综合 ⁄ 共 2152字 ⁄ 字号 评论关闭
# 本程序主要利用PIPE来建立Parent Process与Child Process间的互相连通,
# 利用%STATUS纪录目前Child Process的所有状态,与%CHILDREN纪录所有的Child
# Process。
# Parent Process:负责由CHILD_READ中读取所有CHILD Process的输入,并纪录
# 这些Process目前的状态。当收到INT、HUP、TERM等Signal时,即跳出主要loop
# 并将所有child Process全部杀光...


代码:
#!/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";
}

抱歉!评论已关闭.