PHPでファイル操作を実行する場合、特にマルチプロセスまたはマルチスレッド環境で、操作の原子性とセキュリティを確保することが非常に重要です。 Flock()関数とFSYNC()関数は、一般的に使用される2つのツールです。ファイル操作の整合性を効果的に保証し、データの競争を回避し、損失を書き込むことができます。この記事では、これら2つの機能の役割と、それらを合理的に使用する方法を詳細に紹介します。
Flock()関数は、同じファイルを同時に変更する複数のプロセスを回避するためにファイルをロックするために使用され、データの混乱が生じます。共有ロック( lock_sh )と排他的ロック( lock_ex )の2つのロックタイプが提供されます。
Shared Lock(lock_sh) :複数のプロセスがファイルを読み取ることができますが、書き込みを許可しません。
排他的ロック(lock_ex) :排他的ロック。1つのプロセスがファイルを書き込むことを許可しますが、他のプロセスでは読み取りと書き込みはできません。
サンプルコード:
<?php
$fp = fopen('data.txt', 'c+');
if (flock($fp, LOCK_EX)) { // 排他的ロックを追加します
// ファイルライティング操作を実行します
fwrite($fp, "データを書き込みます\n");
fflush($fp); // ファイルシステムにバッファデータを書き込みます
flock($fp, LOCK_UN); // ロックを解放します
}
fclose($fp);
?>
PHP自体はfsync()関数を直接提供しませんが、 fflush()関数の助けを借りてバッファを更新でき、 fsync()は、オペレーティングシステムがカーネルキャッシュデータをディスクに書き込むことを保証するシステムコールです。 fflush()はバッファをフラッシュしますが、ディスクデータが持続することを保証することはできません。 Linux環境では、 posix_fsyncとともにstream_get_meta_dataおよびfstatを介して実装できます(拡張サポートが必要です)。
サンプルコール(サポートされている環境):
<?php
$fp = fopen('data.txt', 'c+');
if (flock($fp, LOCK_EX)) {
fwrite($fp, "データを書き込みます\n");
fflush($fp);
// posix_fsyncデータがディスクに書き込まれていることを確認してください
if (function_exists('posix_fsync')) {
posix_fsync($fp);
}
flock($fp, LOCK_UN);
}
fclose($fp);
?>
Atomicity : Flock()は、データ競争を回避して、1つのプロセスのみがファイルに書き込みできるようにします。
セキュリティ: fflush()とfsync() (または同様の関数)を使用して、データがディスクに書き込まれ、システムのクラッシュや電力の故障によりデータが失われるのを防ぎます。
完全な例:
<?php
$file = '/path/to/data.txt';
$fp = fopen($file, 'c+');
if (!$fp) {
die('ファイルを開くことができません');
}
if (flock($fp, LOCK_EX)) {
// ファイルポインターをファイルの終了に移動します,カバレッジを避けてください
fseek($fp, 0, SEEK_END);
fwrite($fp, "安全データを書き込みます\n");
fflush($fp); // 意思PHPバッファデータは、オペレーティングシステムのキャッシュに書き込まれます
// サポートされているシステム環境で,使用fsync系统调用意思数据写入磁盘
if (function_exists('posix_fsync')) {
posix_fsync($fp);
}
flock($fp, LOCK_UN);
} else {
echo "ファイルロックを取得できません";
}
fclose($fp);
?>
flock()は、同時の書き込み中にデータの不正さを防ぐために、ロックメカニズムを介した同時ファイル操作の原子性を保証します。
ffflush()およびfsync()は、データがプログラムバッファーからオペレーティングシステムキャッシュに書き込まれ、ディスクに同期してデータセキュリティを改善することを確認します。
2つの組み合わせは、ファイルライティングプロセスのリスクを大幅に削減でき、ログライティングや安全な書き込みを必要とする構成ファイルの更新などのシナリオに適しています。
開発中のファイル操作の安定性とセキュリティを確保する必要がある場合は、 flock()をfsync()の概念で使用することをお勧めします。
<?php
$file = 'https://m66.net/path/to/data.txt';
$fp = fopen($file, 'c+');
if (!$fp) {
die('ファイルを開くことができません');
}
if (flock($fp, LOCK_EX)) {
fseek($fp, 0, SEEK_END);
fwrite($fp, "安全データを書き込みます\n");
fflush($fp);
if (function_exists('posix_fsync')) {
posix_fsync($fp);
}
flock($fp, LOCK_UN);
} else {
echo "ファイルロックを取得できません";
}
fclose($fp);
?>