ファイルの権限変更を使用すると、chmod
既存のファイル記述子は以前の権限でファイルにアクセスできます。
権限の変更により、既存のファイル記述子がすぐに閉じたり、失敗したり、使用できなくなったりすることがありますか?
答え1
カーネルはファイル記述に対する権限を確認しません。元のファイルにアクセスしたことがない他のプロセスにコピーすることもできます。FD転送。
手動で試すことができる唯一の方法だと思います。プロセスを学ぶファイルディスクリプタを開き、トリッキーな方法で閉じます1。これらの「狡猾なトリック」の例は、デバッガ(gdb
)を接続してそれを使用してfdを閉じることです。
これは非常に極端なことです。FDが突然終了した場合、プロセスがどのように機能するかを知る方法はありません。場合によっては、プロセスにメモリーにマップされたファイルがある可能性があるため、そのファイルを閉じてメモリー・マッピングを削除すると、プロセスが分割エラーによってクラッシュすることが予想されます。
はるかに良いファイルを使用しているプロセスを見つけて手動で終了します。少なくともこの方法では、他のデータを破損することなく正常に終了するように要求できます。
1 コメントで述べたように、これを行う最善の方法は、元のファイルの代わりにfdを指すように変更するdup2
代わりに呼び出すことです。これは、コードが閉じられるとは思わず、fd(number)がリサイクルされたときに非常に奇妙で安全でないタスクを実行できるためです。close
/dev/null
答え2
Philip Coulingが言及した「不適切なトリック」を介さないと、既存のファイル記述子を無効にすることはできません。しかし、(合理的に)移植可能な方法で同様の効果を得ることができる。
foo
すでに開いているプロセスがまだ作成されないようにするには、foo
次のことを実行できますcp foo foo2; chmod -w foo2; mv foo2 foo
。これで、古いファイルを開くすべてのプロセスは、もはやfoo
呼び出されなくなったファイルに書き込みを続けますfoo
(以前よりもハードリンクが1つ少なくなります)。これらのプロセスfoo
は書き込み用に開くことができないため、新しいプロセスには影響しません。
同様の戦略は、読書を防止したい場合ですcp foo foo2; chmod -r foo2; truncate foo; mv foo2 foo
。ここでは前の項目がfoo
切り捨てられました(つまり、削除されずにサイズがゼロに減少します。したがって、すでに開いているプロセスは、foo
次に読み取ろうとすると何も表示されず、新しいプロセスを開くことができませんfoo
。しかし、これが機能するという保証はありません。すべてのプロセスにmmap
edがあるfoo
場合、切り捨てが実際にこれらのマッピングに影響するかどうかを指定する方法はありません。
答え3
これは非常に面白い質問であり、これを解決することは実際にNetflixを見るよりも日曜日をもっと楽しくします:-)
- 他の答えによると、posixではありません
- 汚いトリック:YMMV、ファイルのマッピングを解除してデバッガトリックを拡張する必要があると確信しています。 (そうです、それは邪悪です。システムコールの間にファイル記述子が無効になることはお勧めできません。しかし、処理することは不可能です。データ構造の一部が消えます)。
- Linuxでは:以下を見るとhttps://upload.wikimedia.org/wikipedia/commons/f/fb/The_Linux_Storage_Stack_Diagram.svg実際には、通常、提案を実装するには、inodeのページキャッシュの場所を検索し、不明な方法で直接見つける必要があります(そうでなければ、すでにマッピングされているメモリがまだ存在するため、システムコールは必要ありません)。 (注:ページキャッシュへのアクセスをロックしたり、プロセスフォークを防止したりしないと、ユーザースペースで確実に実行されない可能性があります。)
- (Linux)強制ロックマウントオプション+ flockを試してみることはできますが、ロックを「盗む」ことができるかどうかはわかりません。
これは次のことを意味します。
- 私たちはメモリマッピングが好きではありません
- 私たちは、FS階層の下で作業を妨げるのが好きではありません。
ユースケースによって異なる可能性もあります。
- オーバーレイファイルシステムを実装します。これによりマッピングが防止され、呼び出しをフィルタリングできます。実際には複雑ではありません。
- ネットワークファイルシステムを使用して同様のタスクを実行する
- 最も重要なのは、サーバープロセスを介してファイルへのアクセスを構成することです(本質的に「オーバーレイファイルシステムの実装と同じですが、移植可能」:-))。