ファイルの共有制御ですが、Perl の flock というのを使ってみました。
- flock について
- flock(FILEHANDLE,OPERATION);
OPERETION には、下記の値を足し算して与えます。
1(共有ロック)
2(排他ロック)
4(ブロックしない)
8(ロック解除)
ファイルを、open して得られた FILEHANDLE にたいして flock します。
ロックできない場合は、ロックできるまで制御は返ってきません。
4(ブロックしない)を指定すると、ロックできない場合に制御が帰ってきます。
つまり、下記の値を与える事になります。
1(共有ロック)
2(排他ロック)
5(共有ロック、ブロックしない)
6(排他ロック、ブロックしない)
8(ロック解除)
ブロックしない設定は CGI では使う場面がないような気がします。
- アクセスカウンターでの例
$LOCK_UN =1; $LOCK_EX =2; $LOCK_NB =4; $LOCK_UN =8; open(FCTR,"+<$fctr"); flock(FCTR,$LOCK_EX); # 排他 lock $no=<FCTR>+ 1; seek(FCTR, 0, 0); printf(FCTR "%d", $no); close(FCTR);close するとアンロックされるので、アンロックする必要はないようです。 明示的にアンロックしようとして、バッファを書き出す前にアンロックして誤動作させてしまう場合があります。
- 誤動作の実験
- 実験用のカウンターをつくり、 2つのフレームから、同時に cgi を起動し、 各2000回、計4000回のカウントアップをおこない、 実際の動作を確認してみました。
共有制御を正しく行なわないと、誤動作する様子が分かります。
実際の動作を確認できますので、お試しください。
カウントアップされないだけでなく、 ファイルの内容がおかしくなってしまう場合もあります。
実験0:ロック(共有制御)をしないと誤動作する例
実験1:アンロックのタイミングによって誤動作する例
(実験1は Perl のバージョンアップによって正常動作するようになりました。)
実験2:ロックし、アンロックする前にバッファを書き出して、正常に動作する例
実験3:ロックし、close によって暗黙にアンロックして、正常に動作する例
実験用プログラムのソース flock.cgi
実験用プログラムのソース flocks.cgi
- 参考
- flockとは?
flock(2) man 2 flock