ロック用のファイルを使ってファイルロックする
ロック用のファイルを作ってそれにロックを掛けることもできます。ファイルロック用のファイルを作って排他制御を行う利点は、更新対象のファイルを削除したり、リネームしたりできることです。
以下のサンプルは前回のサンプルをロック用のファイルを使うように修正したものです。ループ用のスクリプトは前回とまったく同じです。ロックするためのスクリプトはsample_20080815.pl、ループ用のスクリプトは、data_20080815.txtで保存してください。
実行方法は、前回のサンプルを参照してください。
use strict; use warnings; use Fcntl qw/:DEFAULT :flock :seek/; # ロック用のファイル(なければ作成) my $lock_file = "lock"; sysopen(my $lock_fh, $lock_file, O_RDONLY | O_CREAT) or die "Cannot open $lock_file: $!"; # ロック用のファイルを排他ロック(読み込んで書き込むので排他ロック) flock($lock_fh, LOCK_EX) or die "Cannot lock $lock_file: $!"; #上書きするので注意 my $file = "data_20080815.txt"; # 読み書きモードでオープン(あまり安全でない) # O_CREATでファイルがなければ作成する。 sysopen(my $fh, $file, O_RDWR | O_CREAT) or die "Cannot open $file: $!"; my $cnt; $cnt = <$fh>; if (!defined $cnt && $!){ die "Cannot read $file: $!"; } $cnt++; # ファイルポインタを先頭に移動 seek($fh, 0, SEEK_SET) or die "Cannot seek $file: $!"; # 書き込み。 print { $fh } $cnt or die "Cannot Write $file: $!"; # 書き込みサイズにファイルを切り詰める truncate($fh, length $cnt); close $fh or die "Cannot close $file: $!"; # closeの際にファイルロックは解除される。 close $lock_fh or die "Cannot close $lock_file: $!"; print "現在のカウント: $cnt\n";
ループスクリプト
use strict; use warnings; use FindBin; my $script = "$FindBin::Bin/sample_20080815.pl"; while (1) { system("perl $script"); # 1より小さいランダムな数 my $random = rand 1; sleep $random; }
while文を使って、スクリプトを繰り返し実行しています。
コード解説
(1)ロック用のファイルを作成する
# ロック用のファイル(上書きするので注意) my $lock_file = "lock"; sysopen(my $lock_fh, $lock_file, O_RDONLY | O_CREAT) or die "Cannot open $lock_file: $!";
ロック用のファイルを作成します。
(2)flock関数を使ってロック用ファイルをロックする
flock関数を使ってロック用ファイルをロックしています。
# ロック用のファイルを排他ロック(読み込んで書き込むので排他ロック) flock($lock_fh, LOCK_EX) or die "Cannot lock $lock_file: $!";
このファイルをロックできたプロセスだけが、更新対象のファイルにアクセスを行うようにします。このロックに続いて、更新対象のファイルをオープンしてファイルを更新します。
(3)ロックの解除
# closeの際にファイルロックは解除される。 close $lock_fh or die "Cannot close $lock_file: $!";
ロック用ファイルをクローズすることで、ロックが解除されます。