Perl-process-management

提供:Dev Guides
移動先:案内検索

Perl-プロセス管理

Perlをさまざまな方法で使用して、要件に従って新しいプロセスを作成できます。 このチュートリアルでは、Perlプロセスを作成および管理する重要で最も頻繁に使用されるいくつかの方法をリストします。

  • 特別な変数 $$ または $ PROCESS_ID を使用して、現在のプロセスIDを取得できます。
  • 上記の方法のいずれかを使用して作成されたすべてのプロセスは、*%ENV *変数を使用して独自の仮想環境を維持します。
  • * exit()*関数は常にこの関数を実行する子プロセスのみを終了し、実行中のすべての子プロセスが終了しない限り、メインプロセス全体は終了しません。
  • 開いているすべてのハンドルは子プロセスでdup()処理されるため、1つのプロセスでハンドルを閉じても他のプロセスには影響しません。

バックスティック演算子

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
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
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

system()関数

  • system()*関数を使用して、Unixコマンドを実行することもできます。このコマンドの出力は、perlスクリプトの出力に送られます。 デフォルトでは、画面、つまりSTDOUTですが、リダイレクト演算子を使用して任意のファイルにリダイレクトできます>-
#!/usr/bin/perl

system( "ls -l")

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
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
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

コマンドに$ PATHや$ HOMEなどのシェル環境変数が含まれている場合は注意してください。 次の3つのシナリオを試してください-

#!/usr/bin/perl

$PATH = "I am Perl Variable";

system('echo $PATH');  # Treats $PATH as shell variable
system("echo $PATH");  # Treats $PATH as Perl variable
system("echo \$PATH"); # Escaping $ works.

1;

上記のコードが実行されると、シェル変数$ PATHの設定に応じて次の結果が生成されます。

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
I am Perl Variable
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

fork()関数

Perlは、同じ名前のUnixシステムコールに対応する* fork()*関数を提供します。 fork()システムコールが使用可能なほとんどのUNIXライクプラットフォームでは、Perlのfork()が単にそれを呼び出します。 fork()システムコールが利用できないWindowsのようないくつかのプラットフォームでは、インタプリタレベルでfork()をエミュレートするためにPerlを構築することができます。

fork()関数は、現在のプロセスを複製するために使用されます。 この呼び出しは、同じポイントで同じプログラムを実行する新しいプロセスを作成します。 子pidを親プロセスに、0を子プロセスに、フォークが失敗した場合はundefを返します。

プロセス内で* exec()*関数を使用すると、要求された実行可能ファイルを起動できます。この実行可能ファイルは別のプロセス領域で実行され、exec()はそのプロセスと同じ終了ステータスで終了する前に実行を待ちます。

#!/usr/bin/perl

if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";

} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

上記のコードが実行されると、次の結果が生成されます-

Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777
  • wait()および waitpid()*は、fork()によって返される擬似プロセスIDとして渡すことができます。 これらの呼び出しは、擬似プロセスの終了を適切に待機し、そのステータスを返します。 * waitpid()*関数を使用して子供を待たずに分岐すると、ゾンビが蓄積されます。 Unixシステムでは、次のように$ SIG \ {CHLD}を「IGNORE」に設定することでこれを回避できます-
#!/usr/bin/perl

local $SIG{CHLD} = "IGNORE";

if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";

} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

上記のコードが実行されると、次の結果が生成されます-

Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1

kill()関数

Perlの* kill( 'KILL'、(プロセスリスト))*関数を使用して、fork()によって返されたIDを渡すことにより、疑似プロセスを終了できます。

pseudo-process()でkill( 'KILL'、(Process List))を使用すると、通常、擬似プロセスを実装するスレッドがリソースをクリーンアップする機会を得られないため、メモリリークが発生する可能性があることに注意してください。

  • kill()*関数を使用して、他の信号をターゲットプロセスに送信できます。たとえば、次のようにSIGINTをプロセスID 104および102に送信します-
#!/usr/bin/perl

kill('INT', 104, 102);

1;