发信人: demonalex(啊神) 
整理人: workingnow(2003-10-15 04:59:37), 站内信件
 | 
 
 
[灌水]PERL进程、管道、信号
 
 [日记文]关于Perl的'进程'[perl_three I]
 
 writer:demonalex
 email:demonalex_at_dark2s.org
 
 
     PERL灵活的进程函数是为了复制进程用于分担任务与程序的工作量。
 
     PERL中复制进程有两种方法:fork()、system()与exec()。
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 fork()部分:*NIX传统的复制进程方法
 ================================================================================================
 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
 fork()函数:
 
 作用:进程复制函数。
 
 用法:$pid=fork();
      
 讲解:
 无参数;当本进程为父进程时返回值为子进程的PID值,当进程为子进程时返回值
 为0。
 
 实例:
 -------------------------------------------
 #!usr/bin/perl -w
 $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()
 的返回值。
 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
 getppid()函数:
 
 作用:在子进程中调用此函数来获得父进程PID值。
 
 用法:$parent=getppid();
 
 讲解:无参数,调用后其返回值为父进程的PID值。
 
 实例:
 -------------------------------------------
 #!usr/bin/perl -w
 $pid=fork();                              #复制进程
 die "Error:$!\n" unless defined $pid;     #制定错误机制,此步可略
 if($pid==0){                              #当进程为子进程则进入条件,当进程为父进程则跳过到程序结束                          
 $parent=getppid();                        #通过getppid()得到父进程PID值
 print"This is a sub pid:$$,the parent is $parent\n";    #在STDOUT打印子进程PID值与其父进程PID值
 }
 exit 1;                                   #退出程序
 -------------------------------------------
 注意:楼上的getppid()实例无法在WIN32下通过,建议使用*nix平台。
 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
 关于使用fork():通过fork()创建的子进程共享了父进程的所有变量、句柄等当前值。
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 system()与exec()部分:更直观的进程调用
 ================================================================================================
 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
 system()函数:
 
 作用:直接生成子进程。
 
 用法:$result=system('dir/w *.bat'); 或 $result=system('dir/w','*.bat');
 
 讲解:参数为SHELL语句。当函数能正常调用时返回值为0(注意:此与其他函数不一致),其他返回值均为错误。
 
 实例:
 -------------------------------------------
 #!usr/bin/perl -w
 print STDOUT system('dir/w','*.pl');      #把system()函数中的子进程SHELL语句'dir/w *.pl'的结果输出到STDOUT中
 exit 1;                                   #退出程序
 -------------------------------------------
 #在c:\根目录下运行结果为:
 C:\>perl mm.pl
  驱动器 C 中的卷没有标签。
  卷的序列号是 2629-08EF
 
  C:\ 的目录
 
 aaa.pl         bbb.pl         zzz.pl         xxx.pl         SOCK.PL
 connect.pl     connect2.pl    connect3.pl    connect4.pl    connect5.pl
 connect6.pl    connect7.pl    udpc.pl        udps.pl        connect8.pl
 connect10.pl   fork.pl        pidd.pl        mm.pl
               19 个文件          7,503 字节
                0 个目录  5,514,014,720 可用字节
 0
 
 #注意楼上最后的'0',这就是返回后的数值,楼上表示程序正常调用了system()函数中的shell语句了。
 -------------------------------------------
 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
 exec()函数:
 
 作用:以指定的SHELL语句代替原进程。
 
 用法:$result=exec('copy *.bat c:\'); 或 $result=exec('copy','*.bat','c:\');
 
 讲解:参数为SHELL语句,成功调用后返回值为undef,其他返回值均为失败。使用此函数后生成的新进程与原进程为同一进程,
 有相同的PID,共享变量语柄等一切当前值。
 
 实例与system()相当,所以不作讨论了。
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
 [日记文]关于Perl的'管道'[perl_three II]
 
 writer:demonalex
 email:demonalex_at_dark2s.org
 
 附:关于'Perl的管道'部分内容博大精深,而本人又水平有限,所以只好草草了事,如果有哪里不妥还望各位前辈指点:)
 
     管道是为了使不同进程可以进行通信的制定的。管道是*NIX编程的重点。
 
     与其相关的函数有:open()、pipe()等等。
 
 open():作打开句柄用。
 格式:open(FILEHANDLE,"符号+参数");
 
 例子:open(NIX,'|wc -lw');    #打开名为NIX的管道,其进程为‘wc -lw’,管道为写入。
      open(DDD,"dir c:\|");   #打开名为DDD的管道,其进程为‘dir c:\’,管道为读取。
  
 讲解:FILEHANDLE(句柄)包括很多成分,如文件句柄、SOCKET句柄、管道句柄,此文只谈到管道句柄。
      第二个参数为双引号或单引号相括着的管道符号与参数。管道符号为"|",把管道符号放到参数
      的左边为‘只读’,放到右边为‘只写’,如果两边都有便为双向管道(既可读也可写)。
 
 简单的管道实例:
 
 #!usr/bin/perl -w
 open(AAA,'dir d:|');    #打开管道AAA,进程为'dir d:',只读
 @bbb=<AAA>;             #从管道中读取内容,并压入@bbb数组
 print"@bbb\n";          #把@bbb数组全部输出到STDOUT
 close AAA;              #关闭管道AAA
 exit 1;                 #退出程序
 
 〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
 
 pipe():创建管道对。
 格式: pipe(READ,WRITE);
 
 实例:pipe(README,WRITEME);    #创建了一个管道对,'README'用于读,'WRITEME'用于写。
      $aaa=pipe(AAA,BBB);      #创建了一个管道对,'AAA'用于读,'BBB'用于写,$aaa变量为调用pipe()的返回值。
 
 讲解:正常调用后返回值为非零数,第一个参数为被创建的读管道,第二个参数为被创建的写管道。此函数通常配合进程中
      的fork()函数一同使用,步骤是先使用pipe()函数建立管道对,再使用fork()创建新进程,在不同的进程关闭不同的
      管道,这样就可以达到管道间通信的目的了。
 
 〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
 
 close():关闭管道
 格式: close(AAA);
       close BBB;
 
 实例与格式相当,也就不详细介绍了。
 
 讲解:close()在调用时能将子程序的终止代码放到特殊变量$?中;当关闭的是写管道时close()调用将进入堵塞状态直至另一
      端完成它的全部工作为止。
 
 [日记文]关于Perl的'信号'[perl_three III]
 
 writer:demonalex
 email:demonalex_at_dark2s.org
 
     信号其实就是编程里俗称的中断,它使监视与控制其他进程变为有可能。
 
     首先说说通用信号,通用信号归纳起来可以组成以下列表:
 ========================================================================
 信号名          值          标注          解释
 ------------------------------------------------------------------------
 HUP             1           A             检测到挂起
 INT             2           A             来自键盘的中断
 QUIT            3           A             来自键盘的停止
 ILL             4           A             非法指令
 ABRT            6           C             失败
 FPE             8           C             浮点异常
 KILL            9           AF            终端信号
 USR1            10          A             用户定义的信号1
 SEGV            11          C             非法内存访问
 USR2            12          A             用户定义的信号2
 PIPE            13          A             写往没有读取者的管道
 ALRM            14          A             来自闹钟的定时器信号
 TERM            15          A             终端信号
 CHLD            17          B             子进程终止
 CONT            18          E             如果被停止则继续
 STOP            19          DF            停止进程
 TSTP            20          D             tty键入的停止命令
 TTIN            21          D             对后台进程的tty输入
 TTOU            22          D             对后台进程的tty输出
 ------------------------------------------------------------------------
 著明:上表中‘值’列下没有列出的值所对应的信号为系统调用的非标准信号,在此
      文不予以探讨。上表中的第三列‘标注’定义了当进程接受到信号后的操作,
      如:
         A-----终止进程
         B-----忽略进程信号
         C-----终止进程并卸下内核
         D-----停止进程
         E-----恢复进程
         F-----不能截取或忽略进程信号
 ========================================================================
 
     下面就以INT作范例演示一下调用过程吧:
 ---------------------------------------
 #!usr/bin/perl -w
 #c:\test11.pl
 my $aaa=0;                      #对计数器变量$aaa进行负值
 while($aaa<3){                  #进入循环体
 print"Begin\n";                 #打印字符串到STDOUT
 sleep(5);                       #睡眠函数,参数为5秒
 next unless $SIG{INT}=\&demon;  #选择结构,demon子程序值负于中断函数
 }
 sub demon{                      #demon子程序体
 $aaa++;                         #计数器自加
 print"Stop!\n";                 #打印字符串到STDOUT
 }
 exit 1;                         #退出程序
 ---------------------------------------
 输出结果:在SHELL里不停的打印出'Begin'字样,相隔5秒,一但在键盘中执行程序
          中断操作(Control+'c'),屏幕就会打印出'Stop!'字样,不停地继续下去。
 
 中断调用总结:调用需要使用到系统保留全局HASH数组%SIG,即使用'$SIG{信号名}'
              截取信号,截取后将其负某个代码(子函数)的地址值,这代码就是截
              取后要执行的结果了。
 
 
  ---- 一穷二白三光棍:)
 http://demonalex.dark2s.org | 
 
 
 |