
おそれいります。
親プロセスから子プロセスを複数呼び
子プロセスが全て終わった後に次の手順に移行する。。。という処理をflockを使って作っているのですが、
うまくいきません。
下の「main.pl」を実行すると、「lock.pl」を10回呼び出して、
すべて終了したら「OK」と表示したいです。
lockというファイルを全部のプロセスで共有して、
子の全部の処理が終わった時点で、mailにロックが移る。。。という動きを想定したのですが、
なぜか、数回実行しているとMAIN LOCK(1) が最後に発動しているにもかかわらず、
子プロセスが終了していないのに「OK」の表示を出してしまいます。
flockは順番を守らないのでしょうか・・・・?????
どのようにしたらうまく動くでしょうか。。。。
==> main.pl <==
#!/usr/bin/perl
use Fcntl ':flock';
for (1..10){
system("./lock.pl $_ &");
}
sleep 5; # 子プロセスが開始するまで待つ
print qq("MAIN LOCK\n"); # ... (1)
open LC,"+<lock" or die;
flock LC,LOCK_EX;
sleep 1;
print qq("OK\n");
==> lock.pl <==
#!/usr/bin/perl
use Fcntl ':flock';
print qq(lock $ARGV[0]\n!); # ... (2)
open LC,"+<lock" or die;
flock LC,LOCK_EX;
sleep $ARGV[0];
print qq(release $ARGV[0]!\n);
No.4ベストアンサー
- 回答日時:
質問の趣旨に合っているかわかりませんが、プログラムを作ってみました。
ロックした後の処理に時間がかからなければ、順番どおりに実行されると思います。main.pl
--------------------------
#!/usr/bin/perl
foreach (1 .. 10) {
system("./lock.pl $_ &");
}
lock.pl
--------------------------
#!/usr/bin/perl
use Fcntl ':flock';
use POSIX ':sys_wait_h';
$arg = $ARGV[0];
sleep $arg;
$pid = fork();
die "Can't fork: $!" unless defind $pid;
if ($pid) {
do { $kid = waitpid(-1, &WNOHANG); } until $kid == -1;
if ($arg == 10) {
print "MAIN LOCK\n";
open LC, "+<lock" or die;
flock LC, LOCK_EX or die;
print "OK\n";
}
} else {
print "lock $arg\n";
open LC, "+<lock" or die;
flock LC, LOCK_EX or die;
print "release $arg\n";
}
おお!
サンプルありがとうございます!
とりあえず、なるべく現行を変えないでということで、
子スクリプトで実行時にフラグファイルを作るようにして、
そのフラグを親スクリプトが発見するまで待つようにしてみました。
for ( 0 .. 19 ){
system("[子スクリプト] $_ &"); # ←この引数$_を子スクリプトでフラグとして作成
for( 0 .. 600 ){
if( -f $_ ){
last;
}
sleep 1;
}
}
こんな感じにしたら、親のロックが最後になるようになったため
大丈夫になりました!
ループを600にしてるのは、600秒も開始しない場合はなにかおかしいだろうということで
ここには書きませんでしたが、exit 1 するようにしました。
※ しかしながら、この子供って結構重い処理なのですが、6分ぐらい開始しない、ということがありました。
sparcのsolarisではそんなことなかったので、ちょっと驚きました。
No.3
- 回答日時:
No1 です。
> system("./lock.pl $_ &");
上記のように書いた場合は、制御が非常に難しいと思います。& がなければ親プロセス (PPID) は main.pl になりますが、& を付けた場合は main.pl が親プロセスにならず切り離されてしまうからです (私が使っている Linux の場合)。
> 上記のように書いた場合は、制御が非常に難しいと思います。
そのようですね。
実はこのやり方はsolarisで試行錯誤をしてうまく行ったやり方だったのですが、
Linuxであっさりうまくいかなくなり、ご質問させていただきました。
(cygwinでもダメでした・・・)
今あらためて、solarisだと動きは素直でした。。。
No.2
- 回答日時:
プロセスがどのようなタイミングで動くはOSのスケジューラ次第です。
親プロセスのCPUタイムに余裕があるなら、forループに続けて、ロックの獲得・解放まで処理が進みます。
なので、
>子の全部の処理が終わった時点で、mailにロックが移る。。。
と思ったのが敗因かと。
子プロセスとの同期には、waitpidやsigchildなど別の仕掛けがありますので、そちらを使ってみては。
この回答への補足
forループのあとに5秒おいて、必ず子が先に始まるようにしているのですが、
ダメなんですよね・・・
なので、仰っていることの半分くらいはわかるのですが、
>forループに続けて、ロックの獲得・解放まで処理が進みます。
はprint文を入れてログを出してみてもちゃんと最後に(1)が実行されているのですが・・・
>waitpidやsigchildなど別の仕掛け
そうなんですね。調べてみます。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
forkで作れる子プロセス数が限...
-
時間がかかり過ぎたプロセスを...
-
【Excel2016】結合されたセルを...
-
「デバイスは PRN を初期化でき...
-
Perlのモジュールについて
-
グラフのX,Y座標を取得したい
-
例外処理のフローチャートの記...
-
Excel VBAでリンク切れをチェッ...
-
EXECEL VBA コマンドボタンか...
-
VBScriptのデバッグ方法につい...
-
tex についての質問です このコ...
-
fetchrow_arrayとfetchrow_hash...
-
ランダムな単語を得るAPIってあ...
-
モジュールの最大数はいくつな...
-
VBのフォームモジュールと標準...
-
シャープ製品JH-WB1821 と BCG...
-
教えて下さい。
-
ユーザー定義関数に#NAME?が返...
-
windowsXP上で動作する最新版の...
-
クリアーとデリート
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
AIX6でファイルのタイムスタン...
-
実行中のcpan processを終了さ...
-
標準入出力先の検知
-
LinuxにおいてのPerlのプログラ...
-
時間がかかり過ぎたプロセスを...
-
open MAILでの"|"
-
Perlの処理待ちコマンド
-
ハマったので助けて~。Apache...
-
system関数とqx演算子の違いに...
-
Perlでpopen()的なものを使って...
-
system から得た情報を変数に入...
-
forkで作れる子プロセス数が限...
-
ディスク容量について
-
Parallel::ForkManagerについて
-
perl から unix コマンドを入...
-
Epoch time
-
Perlでexitコードを取得する方法
-
macでperl perldocについての...
-
common lispのコード
-
forkしてもバックグラウンドで...
おすすめ情報