排他制御
Perlで排他制御を行うには、
flockを使うのが簡単です。
ただし、
flockはOSに依存し、使えないOSもあるようです。
UNIX系OSなら確実に使えるようなので、普通のLinuxサーバーなら問題ありません。
排他制御は、複数のプロセスが同時に同じファイルの操作を行い、
あるプロセスが書き込み処理中に他のプロセスがファイルを読み込み、データが破損したり、
複数のプロセスで同時に書き込みを行い、データが混じったりするのを防ぐために行います。
open(FILE,"+<file.txt");
flock(FILE,2);
処理;
close(FILE);
のように、1番目の引数にファイルハンドルを渡し、
2番目の引数に
flockのモードを引数を渡します。
flockのモード
1 | 書き込みロック |
2 | 読み書きロック |
5 | 書き込みロック |
6 | 読み書きロック |
8 | ロック解除 |
8のロック解除は、
closeすれば自動的に解除されるので普通は使わない。
5と6は、他のプログラムにロックされていなければ1を返す。されていれば0を返すだけで、それだけでは排他制御にならないので普通は使わない。
通常、1か2を使う。
1は、ロック中は書き込みができないが読み込みはできる。
2は、ロック中は読み込みも書き込みもできない。
2を使うことが多いと思います。
Perlでファイルに書き込む際、
open(FILE,"+>text.txt");
のように、
openに「+>」を指定し、
常に空ファイルに書き込むことが多いと思いますが、
open(FILE,"+>text.txt");
flock(FILE,2);
書き込み処理
close(FILE);
のような場合、
openでファイルが空になり、その次の行でファイルをロックしますので、
open直後でロックする前に他のプロセスに読み込まれたばあい、空のファイルが読み込まれてしまうため、データが消失する可能性があります。
「+>」による新規ファイルの作成の場合、
複数プロセスによる同時書き込みなどでデータが破損することはないと思いますが、
消失することは考えられるので使わないことが多いです。
open(FILE,"+<test.txt");
flock(FILE,2);
seek(FILE,0,0);
書き込み処理
truncate(FILE,tell(FILE));
close(FILE);
のように、
上書きモードで
openし、
flock
seekでファイルの書き込み位置を先頭にセットし、
書き込んだ後でファイルの長さを
truncateで現在位置までに切り詰めます。
tellはファイルの現在位置を返します。