Perl 使用管道实现进程间的通信

作用:进程复制函数。 
用法:$pid=fork();    
讲解: 
无参数; 当本进程为父进程时返回值为子进程的PID值,当进程为子进程时返回值为0。 

实例: 

#!usr/bin/perl -
$pid=fork();  #复制进程,并把返回值附入$pid 
die "Error:$!\n" unless defined $pid;  #制定程序的错误机制,此步可略 
if$pid!=0{  #条件选择,测试$pid值,以确定为子进程还是父进程
print"This is a main pid!PID is $$!\n"; #$pid值不等于0,此为父进程(:$$为保留变量,其值为此进程的PID) 
}else{  #否则.. 
print"This is a sub pid!PID is $$!\n";  #$pid值为0,此为子进程 

exit 1;

                       
分析实例: 
楼上的程序没有父进程与子进程的明显分化,要将它们分开就要靠测试$pid的值,所以对fork()函数调用来说条件语句是非常重要的,需要通过它们来辨别fork()的返回值。 

注:fork()函数
Does a fork(2) system call to create a new process running the same program at the same point.
fork以后,子进程从fork点开始和主进程运行相同的程序,所以可以通过测试$pid来使主进程和子进程运行不同的程序, 子进程所做的工作结束后应该退出 ,不然会继续运行if代码块以后的父进程的程序,这样会运行两次父进程的程序。

fork,It clones off a duplicate process identical in virtually every aspect to its parent,  including variable settings and open files.(《perl cookbook》)
!/usr/bin/perl -w

        my $pid = fork;
        if $pid = 0) {
                print "is parent\n";
        } else {
                # this is the child process
                print "is child\n";  #子进程退出,会继续运行if一下的程序。
        }

        print 'program after "if"'."\n" #会打印两次,一次是父进程打印,一次是子进程打印的。


;  

exit 0;  #子进程退出,不会运行if以后的程序
        }

        print "\n" #只有父进程打印一次


pipe():创建管道对。 
格式: pipe(READ,WRITE); 

The pipe function creates two connected filehandles,a reader and writer,whereby anything written to the writer can be read from the reader.(摘自《perl cookbook》)
pipe创建两个连接的句柄,一个读,一个写,任何写入到writer的都可以从reader中读出。

实 例:pipe(README,WRITEME); #创建了一个管道对,"README"用于读,"WRITEME"用于写。
$aaa=pipe(AAA,BBB); #创建了一个管道对,"AAA"用于读,"BBB"用于写,$aaa变量为调用pipe()的返回值。 

讲解:正常调用后返回值为非零数,第一个参数为被创建的读管道,第二个参数为被创建的写管道。此函数通常配合进程中 的fork()函数一同使用,步骤是先使用pipe()函 数建立管道对,再使用fork()创建新进程,在不同的进程关闭不同的管道,这样就可以达到管道间通信的目的了。 


close(): 关闭管道 
格式: close(AAA); 
close BBB; 

讲 解:close()在调用时能将子程序的终止代码放到特殊变量$?中;当关闭的是写管道时close()调用将进入堵塞状态直至另一端完成它的 全部工作为止。 
 
子进程通过父进程获得输入 
-w
my $uid ="test 123";

pipe(CHILD_RDR, PARENT_WTR;
my $pid ;
$pid != 0) {
        #this is parent process
        close CHILD_RDR;
        print PARENT_WTR "$uid";
else {
        # this is the child process
        close PARENT_WTR;
        $u = <CHILD_RDR>; 
        print $u; 

}


父进程通过子进程获得输入
(PARENT_RDR; 
my $pid == 0this is child process
        close PARENT_RDR;
        print CHILD_WTR this is the parent process
        close CHILD_WTR<PARENT_RDR; 

}




子进程和父进程双向通信:
#!/usr/bin/perl -w 
# pipe1 - bidirectional communication using two pipe pairs 
#         designed for the socketpair-challenged 
use IO::Handle; # thousands of lines just for autoflush :-( 


pipe(PARENT_RDR,CHILD_WTR); # XXX: failure? 
pipe(CHILD_RDR,PARENT_WTR); # XXX: failure? 
CHILD_WTR->autoflush(1);  
PARENT_WTR->autoflush(1); 


if ($pid = fork) { 
  #this is parent process 
  close PARENT_RDR; close PARENT_WTR; 
  print CHILD_WTR "Parent Pid $$ is sending this\n"; 
  chomp($line = <CHILD_RDR>); 
  print "Parent Pid $$ just read this: `$line'\n"; 
  close CHILD_RDR; close CHILD_WTR; 
  waitpid($pid,0); 

else 

  #this is child process 
  die "cannot fork: $!" unless defined $pid; 
  close CHILD_RDR; close CHILD_WTR; 
  chomp($line = <PARENT_RDR>); 
  print "Child Pid $$ just read this: `$line'\n"; 
  print PARENT_WTR "Child Pid $$ is sending this\n"; 
  close PARENT_RDR; close PARENT_WTR; 
  exit; 


改进版:

#!/usr/bin/perl -w
  # pipe6 - bidirectional communication using socketpair
  # "the best ones always go both ways"
  
  use Socket;
  use IO::Handle;
  # We say AF_UNIX because although *_LOCAL is the
  # POSIX 1003.1g form of the constant, many machines
  # still don't have it.
  socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
      or die "socketpair: $!";
  
  $child->autoflush(1);
  $parent->autoflush(1);
  
  if ($pid = fork) {
      close $parent;
      print $child "Parent Pid $$ is sending this\n";
      chomp($line = <$child>);
      print "Parent Pid $$ just read this: '$line'\n";
      close $child;
      waitpid($pid,0);
  } else {
      die "cannot fork: $!" unless defined $pid;
      close $child;
      chomp($line = <$parent>);       print

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...