flock
(PHP 4、PHP 5)
flock — 軽量の勧告ファイル ロック
説明
bool flock ( int $handle , int $operation [, int &$wouldblock ] )
PHP は、勧告的な方法ですべてのファイルをロックする軽量の方法をサポートしています (つまり、アクセスするすべてのプログラムが同じ方法でロックする必要があります。そうしないと機能しません)。
注:
Windows では flock() が強制されます。
flock() オペレーションのハンドルは、開いているファイル ポインタである必要があります。
共有ロック (プログラムの読み取り) を取得するには、operation を LOCK_SH に設定します (PHP 4.0.1 より前のバージョンでは 1 に設定)。
排他ロック(プログラムの書き込み)を取得するには、操作を LOCK_EX に設定します(PHP 4.0.1 より前のバージョンでは 2 に設定)。
ロック (共有または排他) を解放するには、操作を LOCK_UN に設定します (PHP 4.0.1 より前のバージョンでは 3 に設定)。
ロック時に flock() をブロックしたくない場合は、操作に LOCK_NB を追加します (PHP 4.0.1 より前のバージョンでは 4 に設定)。
flock() を使用すると、任意のプラットフォーム (ほとんどの Unix 派生製品や Windows も含む) で使用できる単純な読み取り/書き込みモデルを実装できます。ロックがブロックされる場合 (EWOULDBLOCK エラー コードの場合)、オプションの 3 番目のパラメーターは TRUE に設定されます。ロック操作は fclose() によって解放することもできます (コードの実行が完了すると自動的に呼び出されます)。
成功した場合は TRUE を返し、失敗した場合は FALSE を返します。
例 #1 flock() の例
$fp = fopen("/tmp/lock.txt", "w "); if (flock($fp, LOCK_EX)) { // 排他的ロックを実行
fwrite($fp, "ここに何かを書き込む ");
flock($fp, LOCK_UN); // ロックを解放} else {
echo "ファイルをロックできませんでした!";
}
fclose($fp);
?>
注:
flock() にはファイル ポインタが必要なため、書き込みモードで開くファイルへのアクセスを保護するために特別なロック ファイルを使用する必要がある場合があります (fopen() に「w」を追加します)関数 " または "w ")。
警告
flock() は、NFS およびその他の一部のネットワーク ファイル システムでは使用できません。詳細については、オペレーティング システムのマニュアルを確認してください。
一部のオペレーティング システムでは、flock() がプロセス レベルで実装されます。マルチスレッド サーバー API (ISAPI など) を使用する場合、ファイルを保護するために flock() に依存することができない場合があります。これは、ファイルが同じサーバー インスタンス内の他の並列スレッドで実行されている PHP スクリプトによって処理される可能性があるためです。
flock() は、FAT やその派生物などの古いファイル システムをサポートしません。したがって、この環境では常に FALSE が返されます (特に Windows 98 ユーザーの場合)。
PHP でのファイル ロック関数 flock 関数の使用法の概要:
構文:
bool flock (int $handle, int $オペレーション [, int &$wouldblock ])
flock() オペレーションのハンドルは、開いているファイル ポインタでなければなりません。
1. 共有ロック (リーダー) を取得するには、operation を LOCK_SH に設定します (PHP 4.0.1 より前のバージョンでは 1 に設定)
2. 排他ロックを取得するには(ライター)、操作を LOCK_EX に設定します (PHP 4.0.1 より前のバージョンでは 2 に設定)
3. ロック (共有または排他) を解放するには、操作を LOCK_UN に設定します (PHP 4.0.1 より前のバージョンでは)
4. ロック時に flock() をブロックしたくない場合は、操作に LOCK_NB を追加します (PHP 4.0.1 の以前のバージョンでは 4 に設定)
以下を参照してください。コード:
a.php
$file = "temp.txt";
$fp = fopen($file, 'w');
if(flock($fp, LOCK_EX)){
fwrite( $fp, "abc");
sleep(10);
fwrite($fp, "123");
flock($fp, LOCK_UN);
}
fclose($ fp);
?>
b.php
$file = "temp.txt";
$fp = fopen($file, 'r');
エコー fread($fp, 100);
fclose($fp);
?>
a.php を実行した後、すぐに b.php を実行すると、次の出力が表示されます。
abc
a.php が実行されるまで待ってから、b.php を実行すると、次の出力が表示されます。
abc
>123
明らかに、a.php がファイルを書き込むとき、データが大きすぎて時間がかかります。このとき、b.php は不完全なデータを読み取ります。b.php を修正した後、
b.php を次のように変更します:
$file = " temp.txt";
$fp = fopen($file, 'r');
if (flock($fp, LOCK_EX)) {
echo fread( $fp, 100);
flock($fp, LOCK_UN);
} else{
echo "ファイルのロックに失敗しました...";
}
fclose($fp); ?>
a.php を実行した後、すぐに b.php を実行します。b.php は a.php が完了するまで (つまり 10 秒後) 待機することがわかります。表示中:
abc
123
読み取り データは完了しましたが、時間が長すぎます。b.php に変更を加える前に、書き込みロックが解放されるまで待つ必要があります。
b.php を次のように変更します。
php
$file = "temp.txt";
$fp = fopen($file, 'r');
if (flock($fp, LOCK_SH | LOCK_NB)) {
echo fread ($fp, 100);
flock ($fp, LOCK_UN);
} else{
echo “ファイルのロックに失敗しました…”;
}
fclose ($fp) ;
?>
a.php を実行した後、すぐに b.php を実行すると、次の出力が表示されます:
ファイルのロックに失敗しました...
ロックが行われたことを証明します上記のように待ち時間が長くなりますが、代わりにファイル障害ステータスを返すこともできます。
Script House 編集者の結論:
ファイルをキャッシュするときは、関連するロックを選択することをお勧めします。そうしないと、読み取られたデータが不完全になったり、データが繰り返し書き込まれたりする可能性があります。
file_get_contents はロックを選択できないようです。デフォルトでどのようなロックを使用しているのかわかりません。とにかく、ロックしないと得られる出力は不完全なデータと同じです。