ウィキペディアのものと比較して、ファイル記述子のより単純化された記述は何でしょうか?なぜそれらが必要なのですか?たとえば、シェルプロセスを例に取って、それをどのように適用しますか?
プロセステーブルに複数のファイル記述子が含まれていますか?はいの場合、なぜですか?
ウィキペディアのものと比較して、ファイル記述子のより単純化された記述は何でしょうか?なぜそれらが必要なのですか?たとえば、シェルプロセスを例に取って、それをどのように適用しますか?
プロセステーブルに複数のファイル記述子が含まれていますか?はいの場合、なぜですか?
回答:
簡単に言うと、ファイルを開くと、オペレーティングシステムはそのファイルを表すエントリを作成し、開かれたファイルに関する情報を保存します。したがって、OSで100個のファイルが開かれている場合、OS(カーネルのどこか)には100個のエントリがあります。これらのエントリは、(... 100、101、102 ....)のような整数で表されます。このエントリ番号はファイル記述子です。したがって、オペレーティングシステムで開かれたファイルを一意に表すのは単なる整数です。プロセスが10個のファイルを開く場合、プロセステーブルにはファイル記述子の10個のエントリがあります。
同様に、ネットワークソケットを開くと、それも整数で表され、ソケット記述子と呼ばれます。御理解いただけることを願います。
/proc
常に開くため、実行を妨げます。
open()
別の実行中のプロセスを参照してください。3.ファイルディスクリプタ持ってしまった場合でも、あなたのファイルディスクリプタ3を与えるのPOSIX定義をopen()
:「open()関数が最も低いという名前のファイルのファイルディスクリプタを返しますそのプロセスに対して現在開いていないファイル記述子です。 " (強調を追加)。
ファイル記述子は、ファイルとソケットのリソースを識別するためにユーザーとカーネル空間間のインターフェースで使用される不透明なハンドルです。したがって、open()
またはsocket()
(カーネルへのインターフェイスへのシステムコール)を使用すると、整数であるファイル記述子が与えられます(これは実際にはプロセスのu構造へのインデックスですが、重要ではありません)。したがって、あなたがシステムコールを使用して、カーネルと直接インタフェースしたい場合はread()
、write()
、close()
などの使用ハンドルはファイルディスクリプタです。
stdio
インターフェースであるシステムコールにオーバーレイされた抽象化の層があります。これにより、基本的なシステムコールよりも多くの機能/機能が提供されます。このインターフェースの場合、取得する不透明なハンドルはFILE*
であり、fopen()
呼び出しによって返されます。使用する多くの多くの機能がありますstdio
インターフェイスはfprintf()
、fscanf()
、fclose()
あなたの人生を容易にするためにそこにです。Cにおいて、stdin
、stdout
、及びstderr
でありFILE*
、UNIXにそれぞれのファイル記述子にマップされ0
、1
そして2
。
馬の口から聞いてください:APUE(リチャード・スティーブンス)。
カーネルにとって、開いているすべてのファイルはファイル記述子によって参照されます。ファイル記述子は負でない数です。
既存のファイルを開くか、新しいファイルを作成すると、カーネルはファイル記述子をプロセスに返します。 カーネルは、使用中のすべてのオープンファイル記述子のテーブルを保持します。ファイル記述子の割り当ては、通常、順次であり、空きファイル記述子のプールからの次の空きファイル記述子としてファイルに割り当てられます。ファイルを閉じると、ファイル記述子が解放され、さらに割り当てることができます。
詳細については、この画像を参照してください。
ファイルの読み取りまたは書き込みを行う場合、open()またはcreate()関数呼び出しによって返されたファイル記述子でファイルを識別し、それをread()またはwrite()の引数として使用します。
慣例により、UNIXシステムシェルは、ファイル記述子0をプロセスの標準入力に関連付け、ファイル記述子1を標準出力に関連付け、ファイル記述子2を標準エラーに関連付けます。
ファイル記述子の範囲は0〜OPEN_MAXです。ファイル記述子の最大値はで取得できますulimit -n
。詳細については、APUE Bookの第3章を参照してください。
osqueryi <<< echo '.all process_open_files'
してbashシェルで実行します。
他の答えは素晴らしいものを追加しました。私は私の2セントだけを追加します。
Wikipediaによると、ファイル記述子は負ではない整数です。私が欠けていると思う最も重要なことは、言うことでしょう:
ファイル記述子はプロセスIDにバインドされます。
私たちは、最も有名なファイルディスクリプタが0、1、2 0に対応している知っているSTDIN
、1にSTDOUT
、そして2 STDERR
。
たとえば、シェルプロセスを例に取って、それをどのように適用しますか?
このコードをチェックしてください
#>sleep 1000 &
[12] 14726
id 14726(PID)のプロセスを作成しました。を使用すると、lsof -p 14726
次のようになります。
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sleep 14726 root cwd DIR 8,1 4096 1201140 /home/x
sleep 14726 root rtd DIR 8,1 4096 2 /
sleep 14726 root txt REG 8,1 35000 786587 /bin/sleep
sleep 14726 root mem REG 8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep 14726 root mem REG 8,1 2030544 137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep 14726 root mem REG 8,1 170960 137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6
4番目の列FDとそのすぐ隣の列TYPEは、ファイル記述子とファイル記述子のタイプに対応しています。
FDの値には、次のものがあります。
cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device
しかし、実際のファイル記述子は以下のとおりです。
NUMBER – Represent the actual file descriptor.
数字の後の文字「1u」は、ファイルが開かれているモードを表します。読み取りの場合はr、書き込みの場合はw、読み取りと書き込みの場合はu。
TYPEは、ファイルのタイプを指定します。TYPEの値の一部は次のとおりです。
REG – Regular File
DIR – Directory
FIFO – First In First Out
ただし、すべてのファイル記述子はCHR –キャラクタースペシャルファイル(またはキャラクターデバイスファイル)です。
今、私たちは、のファイル記述子を識別することができSTDIN
、STDOUT
かつSTDERR
簡単でlsof -p PID
、あるいは我々ならば、私たちは同じことを見ることができますls /proc/PID/fd
。
また、カーネルが追跡するファイル記述子テーブルは、ファイルテーブルやiノードテーブルとは異なります。他のいくつかの答えが説明したように、これらは別々です。
これらのファイル記述子は物理的にどこにあり/dev/pts/6
、たとえば何に格納されているかを自問することができます
sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6
まあ、/dev/pts/6
純粋に記憶に住んでいます。これらは通常のファイルではなく、いわゆるキャラクターデバイスファイルです。あなたはこれをチェックすることができます:ls -l /dev/pts/6
そしてc
、私の場合、それらはで始まりcrw--w----
ます。
OSのようなほとんどのLinuxでは、7種類のファイルが定義されています。
その他のポイントFile Descriptor
:
File Descriptors
(FD)は(0, 1, 2, ...)
、開かれているファイルに関連付けられている負でない整数です。
0, 1, 2
に対応する標準FDSTDIN_FILENO
でSTDOUT_FILENO
あり、プログラムの起動時にシェルに代わってデフォルトで開かれますSTDERR_FILENO
(で定義unistd.h
)。
FDは順番に割り当てられます。つまり、割り当て可能な最小の整数値です。
特定のプロセスのFDは/proc/$pid/fd
(UNIXベースのシステムでは)で確認できます。
他の回答への追加として、unixはすべてをファイルシステムと見なします。キーボードは、カーネルの観点からのみ読み取られるファイルです。画面は書き込み専用ファイルです。同様に、フォルダー、入出力デバイスなどもファイルと見なされます。ファイルが開かれるとき、たとえば、デバイスドライバー[デバイスファイル用]がopen()を要求するとき、またはプロセスがユーザーファイルを開くとき、カーネルはファイル記述子を割り当てます。これは、読み取り専用のファイルへのアクセスを指定する整数です。 、書き込みのみなど[参照:https : //en.wikipedia.org/wiki/Everything_is_a_file ]
ファイル記述子(FD):
$ ls mydir 2> errorsfile.txt
標準エラーのファイル記述子は2
です。mydirという名前のディレクトリがない場合、コマンドの出力はファイルerrorfile.txtに保存されます。
「2>」を使用して、エラー出力を「errorfile」というファイルにリダイレクトします。 txt "
したがって、プログラム出力はエラーで乱雑になりません。
答えが出たらいいのに。
どのオペレーティングシステムでも、p1、p2、p3などのプロセス(p)が実行されています。通常、各プロセスはファイルを継続的に使用します。
各プロセスは、プロセスツリー(または別の言い回しではプロセステーブル)で構成されています。
通常、オペレーティングシステムは表して、各プロセスの各ファイルによって数(各プロセスツリー/テーブルに、と言うことです)。
プロセスで使用される最初のファイルであるfile0秒、FILE1第三の、あるFILE2など、および。
そのような番号はファイル記述子です。
通常、ファイル記述子は整数です(0、1、2ではなく、0.5、1.5、2.5ではありません)。
プロセスを「プロセステーブル」として説明することが多く、テーブルに行(エントリ)があることを考えると、各エントリのファイル記述子セルは、エントリ全体を表すために使用されていると言えます。
同様に、ネットワークソケットを開くと、ソケット記述子があります。
一部のオペレーティングシステムでは、ファイル記述子が不足する可能性がありますが、そのようなケースは非常にまれであり、平均的なコンピューターユーザーは心配する必要はありません。
ファイル記述子はグローバルである可能性があります(プロセスAは0で始まり、1で終わる;プロセスBは2で始まり、3で終わる)などですが、私が知る限り、通常、最新のオペレーティングシステムでは、ファイル記述子はグローバルではなく、実際にはプロセス固有です(プロセスAは0で始まり、たとえば5で終わりますが、プロセスBは0で始まり、たとえば10で終わります)。
上記すべての簡略化された応答への追加。
bashスクリプトでファイルを操作している場合は、ファイル記述子を使用することをお勧めします。
例:-
ファイル「test.txt」の読み取りと書き込みを行います。
以下に示すようにファイル記述子を使用します
FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor
# Reading from the file line by line using file descriptor
while read LINE; do
echo "$LINE"
done <&5
# Writing to the file using descriptor
echo "Adding the date: `date`" >&5
exec 5<&- # Closing a file descriptor