ファイルをロックする(flock)
ファイルを読んだり書き込んだりする時に、他の人が同時にそのファイルに何か行おうとすると問題が起きる事があります。その為、ファイルに対する処理を行う前にファイルをロックして、作業中は他の人がそのファイルに作業を行えないようにする必要があります。
ファイルに対するロックを行うにはflock関数を利用します。
flock bool flock(resource handle, int operation)
ファイルをロックします。対象となるハンドルはfopenなどで取得したハン ドルを指定します。 引数: handle 対象となるファイルのハンドル operation ロックの方法 返り値: 成功した場合に TRUE、失敗した場合に FALSE
ロックの方法は下記の通りです。
値 | 説明 |
---|---|
LOCK_SH | 共有ロック |
LOCK_EX | 排他的ロック |
LOCK_UN | ロック解除 |
LOCK_NB | ロック中にflock()でブロックさせない |
共有ロックは、他のユーザーにファイルの読み取りは許可するけれど、書き込みは許可しない場合に使います。排他的ロックは読み込みも書き込みも許可しません。
ロックを行っている最中に他の人が同じファイルを開いてロックをかけようとすると、こちらのロックが解除されるまで他の人は待機した状態となり、こちらのロックが解除されると待機していた人のロックが行われることになります。そうではなく、自分がロックを行っている最中に他の人がロックをかけようとすると、待機させるのではなくすぐにロック失敗とさせる場合に「LOCK_NB」を使います。「LOCK_NB」は単独で指定するのではなく「LOCK_SH | LOCK_NB」のように他の値と同時に指定します。
実際の流れとしては下記のようになります。
$fp = fopen('filename', 'mode'); if (flock($fp, LOCK_EX)){ // ファイルに対する操作を行う flock($fp, LOCK_UN); }else{ print('ファイルロックに失敗しました'); } fclose($fp);
ロックの解除を忘れていても、該当のファイルに対するハンドルをクローズするとロックが解除されます。
サンプルプログラム
では実際に試して見ます。
<html> <head><title>PHP TEST</title></head> <body> <?php $fp = fopen('sample.txt', 'r'); if (flock($fp, LOCK_EX)){ print('ファイルロックに成功しました<br>'); flock($fp, LOCK_UN); }else{ print('ファイルロックに失敗しました<br>'); } $flag = fclose($fp); if ($flag){ print('無事クローズしました'); }else{ print('クローズに失敗しました'); } ?> </body> </html>
上記ファイルをWWWサーバに設置しブラウザ経由で見ると下記のように表示されます。
( Written by Tatsuo Ikura )