私は2つのperlスクリプト(parent.plとchild.pl)を作成しましたが、それらのソースコードは次のとおりです。
parent.pl:
# file parent.pl
$SIG{CHLD} = sub {
while(waitpid(-1, WNOHANG) > 0) {
print "child process exit\n";
}
};
my $pid = fork();
if($pid == 0) {
system("perl child.pl");
exit;
}
while(1) {
open my $fh, "date |";
while(<$fh>) {
print "parent: ".$_;
}
close $fh;
sleep(2);
}
child.pl
#file child.pl
while(1) {
open my $fh, "date |";
while(<$fh>) {
print " child: ".$_;
}
close $fh;
sleep(2);
}
私が欲しいのは、親プロセスとフォークされたサブプロセスが交互に現在の日付を出力することです。しかし、実行するperl parent.pl
と、出力は次のようになります。
$ perl parent.pl
parent: Mon Jan 21 14:53:36 CST 2013
child: Mon Jan 21 14:53:36 CST 2013
child: Mon Jan 21 14:53:38 CST 2013
child: Mon Jan 21 14:53:40 CST 2013
child: Mon Jan 21 14:53:42 CST 2013
child: Mon Jan 21 14:53:44 CST 2013
パイプを開くときに親プロセスがブロックされたようです。
しかし、シグナルCHLDに対して次の操作を削除するとします。
$SIG{CHLD} = sub {
while(waitpid(-1, WNOHANG) > 0) {
print "child process exit\n";
}
};
そして、もう一度実行します。大丈夫そうです。
$ perl parent.pl
parent: Mon Jan 21 14:57:57 CST 2013
child: Mon Jan 21 14:57:57 CST 2013
parent: Mon Jan 21 14:57:59 CST 2013
child: Mon Jan 21 14:57:59 CST 2013
parent: Mon Jan 21 14:58:01 CST 2013
child: Mon Jan 21 14:58:01 CST 2013
しかし、私はまだ困惑していると感じています。パイプを開こうとしたときに親プロセスがブロックされたのはなぜですか?
ゾンビプロセスを取得する必要があるため、SIG{CHLD}関数を削除することはお勧めできません。
誰でも私を助けることができますか?どうもありがとうございます!
================================================== ================
パズルを解くのを手伝ってくれた@Borodinに感謝します。そして、私はこのように変更しようとしましたparent.pl
:
my $main_pid = $$;
$SIG{USR1} = sub {
#sleep(1);
while(waitpid(-1, WNOHANG) > 0) {
print "child process exit\n";
}
};
my $pid = fork();
if($pid == 0) {
$SIG{USR1} = 'IGNORE';
system("perl child.pl");
kill USR1, $main_pid;
exit;
}
while(1) {
open my $fh, "date |";
while(<$fh>) {
print "parent: ".$_;
}
close $fh;
sleep(2);
}
信号はまたはCHLD
によってキックオフされる可能性があるため、別のカスタマイズされた信号を使用しました。そして今はうまく機能しています。open
system
USR1
================================================== ======================
上記の変更にはまだ問題があります。分岐したサブプロセスは、終了する前にUSR1信号を送信します。waitpid
サブプロセスがまだ終了していないため、親プロセスはしばらく前にスリープする必要がある可能性があります。
現在、サブプロセスを手動で取得せず、を設定してい$SIG{$CHLD} = 'IGNORE'
ます。サブプロセスが終了するときに、オペレーティングシステムによってサブプロセスを取得できることを願っています。