Perl プロセス管理

Perlでは、さまざまな方法でプロセスを作成できます。

このチュートリアルでは、いくつかのプロセス管理方法について説明します。

  • 特殊変数を使用して、$$ 或 $PROCESS_IDプロセスIDを取得できます。

  • %ENV ハッシュには親プロセス、つまりシェルの環境変数が格納されます。Perlではこれらの変数を変更できます。

  • exit()通常、子プロセスを終了するために使用され、メインプロセスはすべての子プロセスが終了した後に終了します。

  • 開いているすべてのハンドルは子プロセスで dup() 関数によって複製されます。プロセスがすべてのハンドルを閉じても、他のプロセスには影響しません。


バッククォート演算子

バッククォート演算子を使用すると、Unix コマンドを簡単に実行できます。バッククォート内に簡単なコマンドを挿入できます。コマンド実行後、結果が返されます:

#!/usr/bin/perl

@files = `ls -l`;

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

1;

上記のプログラムを実行すると、出力結果は次のようになります:

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() 関数

次の関数を使用して Unix コマンドを実行することもできます。system()この関数は Unix コマンドを実行し、実行すると結果が直接出力されます。デフォルトでは、現在の Perl の STDOUT が指す場所、通常は画面に送られます。リダイレクト演算子 > を使用して、指定したファイルに出力することもできます:

上記のプログラムを実行すると、出力結果は次のようになります:

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
……

コマンドに $PATH や $HOME などの環境変数が含まれる場合の出力結果に注意する必要があります。次のようになります:

例

#!/usr/bin/perl $PATH = "私は Perl の変数です"; system('echo $PATH'); # $PATH をシェル環境変数として system("echo $PATH"); # $PATH を Perl の変数として system("echo \$PATH"); # $ をエスケープ 1;

上記のプログラムを実行すると、出力結果は次のようになります:

/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() 関数

Perl の fork() 関数は、新しいプロセスを作成するために使用されます。

親プロセスでは子プロセスの PID が返され、子プロセスでは 0 が返されます。エラーが発生した場合(メモリ不足など)は undef が返され、$! に対応するエラーメッセージが設定されます。

fork は exec と組み合わせて使用できます。exec 関数は引用符内のコマンドを実行すると、プロセスが終了します。

例

#!/usr/bin/perl if(!defined($pid = fork())) { # fork でエラーが発生した場合 undef を返す die "子プロセスを作成できません:$!"; }elsif ($pid == 0) { print "子プロセス経由で出力\n"; exec("date") || die "日付を出力できません:$!"; } else { # 親プロセス内 print "親プロセス経由で出力\n"; $ret = waitpid($pid, 0); print "完了したプロセスID:$ret\n"; } 1;

上記のプログラムを実行すると、出力結果は次のようになります:

通过父进程输出
通过子进程输出
2016年 6月19日 星期日 22时21分14秒 CST
完成的进程ID: 47117

プロセスが終了するとき、親プロセスに CHLD シグナルが送信された後、ゾンビプロセスになります。親プロセスが wait と waitpid を使用して終了させる必要があります。もちろん、$SIG{CHLD} を IGNORE に設定することもできます:

例

#!/usr/bin/perl local $SIG{CHLD} = "IGNORE"; if(!defined($pid = fork())) { # fork でエラーが発生した場合 undef を返す die "子プロセスを作成できません:$!"; }elsif ($pid == 0) { print "子プロセス経由で出力\n"; exec("date") || die "日付を出力できません:$!"; } else { # 親プロセス内 print "親プロセス経由で出力\n"; $ret = waitpid($pid, 0); print "完了したプロセスID:$ret\n"; } 1;

上記のプログラムを実行すると、出力結果は次のようになります:

通过父进程输出
通过子进程输出
2016年 6月19日 星期日 22时30分56秒 CST
完成的进程ID: -1

Kill 関数

Perl kill('signal', (Process List))プロセスグループにシグナルを送信します。signal は送信する数値シグナルで、9 はプロセスを強制終了します。

まず、Linux の一般的なシグナルを見てみましょう。次のリストを参照してください:

信号名          值          标注          解释
————————————————————————————————————————————————————————————
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输出

次の例では、プロセス 104 と 102 に SIGINT シグナルを送信します:

例

#!/usr/bin/perl kill('INT', 104, 102); 1;
その他の拡張