![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
おそれいります。
親プロセスから子プロセスを複数呼び
子プロセスが全て終わった後に次の手順に移行する。。。という処理を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で質問しましょう!
似たような質問が見つかりました
- Java Java 南京錠 2 2023/02/04 11:46
- マウス・キーボード キーボードのCaps Lockキーと変換キーの挙動がおかしくなりました。 4 2022/09/04 22:44
- Perl perlのflock関数でロックをかけたままopen関数で何度もファイルを開きなおすことはできますか 3 2023/05/01 22:25
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- その他(学校・勉強) この中で間違ってある説明はありますか?詳しい方に教えていただきたいです。 A. 1つのプログラムが複 2 2023/07/14 01:15
- PHP PostgreSQLからCSV形式でエクスポートする際にカラム内の改行をとる方法 1 2023/02/22 10:05
- ノートパソコン chromebookのcaps lockが外れなくなった 5 2022/07/14 19:23
- Ruby プログラミング 3 2023/06/09 14:30
- UNIX・Linux shellscript内のコマンドを、sudo(toor)として実行 2 2022/09/23 15:05
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
system関数とqx演算子の違いに...
-
実行中のcpan processを終了さ...
-
AIX6でファイルのタイムスタン...
-
Excel VBAでリンク切れをチェッ...
-
Excel VBA 『Call』で呼び出す...
-
例外処理のフローチャートの記...
-
ユーザー定義関数に#NAME?が返...
-
VBAでoutlook365が起動しません。
-
VBAで別モジュールへの変数の受...
-
モジュールの最大数はいくつな...
-
ユーザーフォームに最小化・最...
-
VBでグローバル変数を宣言するには
-
'Range'メソッドは失敗しました
-
Excel VBAで、ユーザーフォーム...
-
サブルーチンを認識しません。
-
エクセルVBAでシートモジュール...
-
Excelシート内セル記述の違いに...
-
perl起動方法
-
【vba】フォームに書いてあ...
-
Excel VBA 定義されたプロージ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
AIX6でファイルのタイムスタン...
-
open MAILでの"|"
-
LinuxにおいてのPerlのプログラ...
-
Perlの処理待ちコマンド
-
Active Directoryでグループに...
-
Perlでexitコードを取得する方法
-
時間がかかり過ぎたプロセスを...
-
実行中のcpan processを終了さ...
-
`ls`標準出力はどこにいった?
-
マルチスレッドとマルチプロセ...
-
system関数とqx演算子の違いに...
-
HELOコマンドが失敗する。
-
Parallel::ForkManagerについて
-
perl から unix コマンドを入...
-
Perlで日本語から始まり記号で...
-
flockの挙動がおかしい。。。
-
macでperl perldocについての...
-
my $pid = open PIPE, "-|";の...
-
Perl はOSによって動作が違った...
-
1行の抜き方とシステム情報の収...
おすすめ情報