Perl 進(jìn)程管理

Perl 中你可以以不同的方法來創(chuàng)建進(jìn)程。

本教程將討論一些進(jìn)程的管理方法。

  • 你可以使用特殊變量 $$$PROCESS_ID 來獲取進(jìn)程 ID。

  • %ENV 哈希存放了父進(jìn)程,也就是shell中的環(huán)境變量,在Perl中可以修改這些變量。

  • exit() 通常用于退出子進(jìn)程,主進(jìn)程在子進(jìn)程全部退出后再退出。

  • 所有打開的句柄會(huì)在子程序中被 dup() 函數(shù)復(fù)制, 所有關(guān)閉進(jìn)程所有句柄不會(huì)影響其他進(jìn)程 。


反引號(hào)運(yùn)算符

使用反引號(hào)運(yùn)算符可以很容易的執(zhí)行 Unix 命令。你可以在反引號(hào)中插入一些簡單的命令。命令執(zhí)行后將返回結(jié)果:

#!/usr/bin/perl

@files = `ls -l`;

foreach $file (@files){
   print $file;
}

1;

執(zhí)行以上程序,輸出結(jié)果如下:

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
……

system() 函數(shù)

你也可以使用 system() 函數(shù)執(zhí)行 Unix 命令, 執(zhí)行該命令將直接輸出結(jié)果。默認(rèn)情況下會(huì)送到目前Perl的STDOUT指向的地方,一般是屏幕。你也可以使用重定向運(yùn)算符 > 輸出到指定文件:

執(zhí)行以上程序,輸出結(jié)果如下:

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
……

你需要注意命令包含環(huán)境變量如 $PATH 或 $HOME的輸出結(jié)果,如下所示:

#!/usr/bin/perl

$PATH = "我是 Perl 的變量";

system('echo $PATH');  # $PATH 作為 shell 環(huán)境變量
system("echo $PATH");  # $PATH 作為 Perl 的變量
system("echo \$PATH"); # 轉(zhuǎn)義 $

1;

執(zhí)行以上程序,輸出結(jié)果如下:

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
我是 Perl 的變量
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

fork() 函數(shù)

Perl fork() 函數(shù)用于創(chuàng)建一個(gè)新進(jìn)程。

在父進(jìn)程中返回子進(jìn)程的PID,在子進(jìn)程中返回0。如果發(fā)生錯(cuò)誤(比如,內(nèi)存不足)返回undef,并將$!設(shè)為對(duì)應(yīng)的錯(cuò)誤信息。

fork 可以和 exec 配合使用。exec 函數(shù)執(zhí)行完引號(hào)中的命令后進(jìn)程即結(jié)束。

#!/usr/bin/perl

if(!defined($pid = fork())) {
   # fork 發(fā)生錯(cuò)誤返回 undef
   die "無法創(chuàng)建子進(jìn)程: $!";
}elsif ($pid == 0) {
   print "通過子進(jìn)程輸出\n";
   exec("date") || die "無法輸出日期: $!";
  
} else {
   # 在父進(jìn)程中
   print "通過父進(jìn)程輸出\n";
   $ret = waitpid($pid, 0);
   print "完成的進(jìn)程ID: $ret\n";

}

1;

執(zhí)行以上程序,輸出結(jié)果如下:

通過父進(jìn)程輸出
通過子進(jìn)程輸出
2016年 6月19日 星期日 22時(shí)21分14秒 CST
完成的進(jìn)程ID: 47117

如果進(jìn)程退出時(shí),會(huì)向父進(jìn)程發(fā)送一個(gè)CHLD的信號(hào)后,就會(huì)變成僵死的進(jìn)程,需要父進(jìn)程使用wait和waitpid來終止。當(dāng)然,也可以設(shè)置$SIG{CHLD}為IGNORG:

#!/usr/bin/perl

local $SIG{CHLD} = "IGNORE";
 
if(!defined($pid = fork())) {
   # fork 發(fā)生錯(cuò)誤返回 undef
   die "無法創(chuàng)建子進(jìn)程: $!";
}elsif ($pid == 0) {
   print "通過子進(jìn)程輸出\n";
   exec("date") || die "無法輸出日期: $!";
  
} else {
   # 在父進(jìn)程中
   print "通過父進(jìn)程輸出\n";
   $ret = waitpid($pid, 0);
   print "完成的進(jìn)程ID: $ret\n";

}

1;

執(zhí)行以上程序,輸出結(jié)果如下:

通過父進(jìn)程輸出
通過子進(jìn)程輸出
2016年 6月19日 星期日 22時(shí)30分56秒 CST
完成的進(jìn)程ID: -1

Kill 函數(shù)

Perl kill('signal', (Process List))給一組進(jìn)程發(fā)送信號(hào)。signal是發(fā)送的數(shù)字信號(hào),9為殺掉進(jìn)程。

首先看看linux中的常用信號(hào),見如下列表:

信號(hào)名          值          標(biāo)注          解釋
————————————————————————————————————————————————————————————
HUP             1           A             檢測(cè)到掛起
INT               2           A             來自鍵盤的中斷
QUIT            3           A             來自鍵盤的停止
ILL               4           A             非法指令
ABRT          6           C             失敗
FPE             8           C             浮點(diǎn)異常
KILL             9           AF            終端信號(hào)
USR1          10          A             用戶定義的信號(hào)1
SEGV          11          C             非法內(nèi)存訪問
USR2          12          A             用戶定義的信號(hào)2
PIPE           13          A             寫往沒有讀取者的管道
ALRM         14          A             來自鬧鐘的定時(shí)器信號(hào)
TERM         15          A             終端信號(hào)
CHLD          17          B             子進(jìn)程終止
CONT         18          E             如果被停止則繼續(xù)
STOP         19          DF            停止進(jìn)程
TSTP          20          D             tty鍵入的停止命令
TTIN            21          D             對(duì)后臺(tái)進(jìn)程的tty輸入
TTOU          22          D             對(duì)后臺(tái)進(jìn)程的tty輸出

以下實(shí)例向進(jìn)程 104 和 102 發(fā)送 SIGINT 信號(hào):

#!/usr/bin/perl

kill('INT', 104, 102);
 
1;