全体的な状況を理解するためにファイル記述子を使用しようとしています。最初に、次のファイル記述子を持つprocess1があるとします。
_process1_
| |
| 0 stdin |
| 1 stdout |
| 2 stderr |
|__________|
次に、ファイル記述子 1 を閉じます。
close(1);
ファイル記述子1は標準出力に変換(指定)します。ファイル構造カーネルからファイルテーブルを開く。
上記のコードを使用すると、ファイル記述子1がプロセステーブルから削除され、次のようになります。
_process1_
| |
| 0 stdin |
| 2 stderr |
|__________|
しかし、カーネルでは何が起こりますか? FILE構造がstdout
解放されましたか? stdoutが特別なファイル(モニター)であり、他のプロセスで使用できる場合はどうすればよいですか? FILE構造が通常のファイル(例:.txt)の場合はどうなりますか?他のプロセスがそのようなファイルを使用している場合はどうなりますか?
答え1
ファイル記述子1は、カーネルのオープンファイルテーブルからstdout FILE構造に変換されます。
これは誤解です。カーネルのファイルテーブルは、ユーザ空間ファイル構造とは何の関係もありません。
とにかく、カーネルには2つのレベルの間接参照があります。参照計算されるファイル自体を表す内部構造があります。参照回数が計算される「オープンファイル記述」があります。その後、参照計算されないファイルハンドルがあります。ファイル構造はinode自体を指します。オープンファイルの説明には、オープンモードとファイルポインタが含まれます。
クローズを呼び出すと、常にファイルハンドルを閉じます。ファイルハンドルが閉じると、開かれたファイル記述の参照回数が減少します。 0になると、開いたファイル記述も解除され、ファイル自体の参照回数が減ります。この値が 0 になると、カーネルのファイル構造が解放されます。
共有リソースは参照計算されるため、あるプロセスは別のプロセスで使用されているリソースを解放する機会がありません。
答え2
この場合、多くのことは起こりません。 stdin、stdout、およびstderrはすべて同じファイル記述子の複製である傾向があります。ファイル記述子の参照カウンタは1ずつ減少します。プログラムを実行するシェルは通常同じファイル記述子を保存するため、ファイル記述子を保存する必要があります。
カーネルは、開いているすべてのファイル(inode)の参照数を保持します。参照数が0より大きい場合、ファイルは保持されます。開いたファイルハンドルに対して別々のカウンタを保持したいと思います。 0に達すると、カーネルはファイルハンドルで使用されているメモリを解放できます。
ファイルへのすべての参照(ディレクトリエントリとファイルハンドル)が削除されると、ファイルシステムコードは再利用するinodeを表示します。ファイル内のすべてのブロックを割り当てることができます。多くのファイルシステムでは、inodeが解放されたときにinodeのブロックポインタを消去します。これにより、削除されたファイルを回復するのが困難です。ディスクの更新はバッファリングされ、後で完了することができます。
答え3
あなたの説明は最後の段落まで正確です。
しかし、カーネルでは何が起こりますか? stdout FILE構造が解放されましたか? stdoutが特別なファイル(モニター)であり、他のプロセスで使用できる場合はどうすればよいですか? FILE構造が通常のファイル(
afile.txt
たとえば)の場合はどうなりますか?他のプロセスがそのようなファイルを使用している場合はどうなりますか?
カーネルはstdin/stdout/stderrについて何も知りません。これはファイル記述子0、1、2にすぎません。これは使用に関する規則です。
最後の段落ではありません。端末ウィンドウが保存されました。ファイル記述子を削除してもファイルは削除されません。ディレクトリエントリのみを削除してもrm
ファイルは削除されません(他の回答の参照計算参照:参照するエントリがない場合、ファイルは削除されます)。したがって、ファイルにディレクトリエントリがなく、どのプロセスでも開かない場合、ファイルは削除されます。