ファイル記述子


Linuxのファイル記述子と開くファイルの関係
1.概要
Linuxシステムではすべてファイルと見なすことができ、ファイルは一般ファイル、ディレクトリファイル、リンクファイル、デバイスファイルに分けられます.ファイル記述子(file descriptor)は、カーネルが開いているファイルを効率的に管理するために作成したインデックスであり、開いているファイルを指す非負の整数(通常は小さな整数)であり、I/O操作を実行するすべてのシステム呼び出しがファイル記述子を通過する.プログラムが起動したばかりの頃、0は標準入力、1は標準出力、2は標準エラーでした.新しいファイルを開くと、そのファイル記述子は3になります.POSIX規格では、ファイルを開くたびに(socketを含む)現在のプロセスで最も利用可能なファイル記述シンボルコードを使用する必要があるため、ネットワーク通信中に少し注意しないと、シリアルが発生する可能性がある.標準ファイル記述子図は次のとおりです.
ファイルの説明は、開いているファイルに対応するモデルを以下の図に示します.
2.ファイル記述の制限
ファイル操作やネットワーク通信のソフトウェアを作成する場合、初心者は一般的に「Too many open files」の問題に遭遇する可能性があります.これは主にファイル記述子がシステムの重要なリソースであるためであり、システムメモリがどれだけあれば開くことができるかというファイル記述子であるが、実際の実装過程でカーネルは対応する処理を行い、一般的に最大開くファイル数はシステムメモリの10%(KBで計算)である(システムレベルの制限と呼ばれる).システムレベルの最大オープンファイル数を表示するにはsysctl-a|grep fsを使用します.file-maxコマンド表示.同時に、カーネルは、あるプロセスがすべてのファイルリソースを消費しないように、単一プロセスの最大オープンファイル数に対してデフォルト値処理(ユーザーレベル制限と呼ばれる)を行い、デフォルト値は一般的に1024であり、ulimit-nコマンドを使用して表示できます.Webサーバでは、システムのデフォルト値ファイル記述子の最大値を変更することによってサーバを最適化することが最も一般的な方法の1つであるCentOS 6.6システムでのファイル記述子の最適化:
1
2
3 ## [root@poe ~] # ulimit -n 1024
ファイル記述子のサイズを一時的に変更
1
2
3 [root@Gin scripts] # ulimit -SHn 65535 [root@Gin scripts] # ulimit -n 65535
ファイル記述子のサイズを永続的に変更するには、次の手順に従います.
1
2
3 [root@Gin ~] # echo '*               -       nofile          65535' >>/etc/security/limits.conf [root@Gin ~] # tail -n1 /etc/security/limits.conf *                -        nofile          65535
 
詳細については、http://blog.csdn.net/kumu_linux/article/details/7877770.
 
3.ファイル記述は、開いているファイルとの関係に合致する
各ファイル記述子は、開いているファイルに対応し、異なるファイル記述子も同じファイルを指します.同じファイルは、異なるプロセスで開くことも、同じプロセスで複数回開くこともできます.システムは、各プロセスに対してファイル記述子テーブルを維持します.このテーブルの値は0から始まるので、異なるプロセスで同じファイル記述子が表示されます.この場合、同じファイル記述子が同じファイルを指したり、異なるファイルを指したりする可能性があります.詳細は具体的に分析し、その概要を理解するには、カーネルによって維持されている3つのデータ構造を表示する必要があります.
    1. プロセスレベルのファイル記述子テーブル
    2. システムレベルのオープンファイル記述子テーブル
    3. ファイルシステムのi-nodeテーブル
 
プロセスレベルの記述子テーブルの各エントリには、単一のファイル記述子に関する情報が記録されます.
    1. ファイル記述子操作を制御するフラグのセット.(現在、このようなフラグはclose-on-execフラグとして1つだけ定義されています)
    2. 開くファイルハンドルへの参照
 
カーネルは、開いているすべてのファイルのファイルに対して、システムレベルの記述子テーブル(open file description table)を維持します.オープンファイルテーブル(open file table)とも呼ばれ、テーブル内の各エントリをオープンファイルハンドル(open file handle)と呼ぶ場合があります.1つのオープン・ファイル・ハンドルには、次のように、1つのオープン・ファイルに関するすべての情報が格納されます.
    1. 現在のファイルオフセット量(read()とwrite()を呼び出したときに更新するか、lseek()を使用して直接変更します)
    2. ファイルを開くときに使用するステータスID(open()のflagsパラメータ)
    3. Open()を呼び出すときに設定された読み取り専用モード、書き込み専用モード、または読み書きモードなどのファイルアクセスモード
    4. 信号駆動に関する設定
    5. ファイルi-nodeオブジェクトへの参照
    6. ファイルタイプ(一般ファイル、ソケット、FIFOなど)とアクセス権
    7. ファイルが保持するロックのリストを指すポインタ
    8. ファイルのサイズや、異なるタイプの操作に関連するタイムスタンプなど、ファイルのさまざまなプロパティ
 
次の図は、ファイル記述子、開いているファイルハンドル、およびi-nodeの関係を示しています.図では、2つのプロセスには開いているファイル記述子がたくさんあります.
プロセスAでは、ファイル記述子1および30は、同じ開いているファイルハンドルを指している(23).これは、dup()、dup 2()、fcntl()を呼び出すか、同じファイルに対してopen()関数を複数回呼び出すことによって形成される可能性があります.
プロセスAのファイル記述子2とプロセスBのファイル記述子2は、同じ開いているファイルハンドルを指している(73).このような状況は、fork()が呼び出された後に発生するか(すなわち、プロセスA、Bは親子プロセス関係である)、またはあるプロセスがUNIXドメインソケットを介して開いたファイル記述子を別のプロセスに渡す場合にも発生する.さらに、異なるプロセスが独自にopen関数を呼び出して同じファイルを開いた場合、プロセス内部の記述子は他のプロセスがファイルを開いた記述子と同じように割り当てられます.
さらに、プロセスAの記述子0とプロセスBの記述子3は、それぞれ異なるオープンファイルハンドルを指すが、これらのハンドルはi-nodeテーブルの同じエントリ(1976)を指し、言い換えれば、同じファイルを指す.このことは、各プロセスがそれぞれ同じファイルに対してopen()呼び出しを開始したためです.同じプロセスで同じファイルを2回開くと、同様のことが起こります.
 
4.まとめ
    1. プロセスレベルのファイル記述子テーブルが存在するため、異なるプロセスで同じファイル記述子が表示されます.同じファイルを指すか、異なるファイルを指す可能性があります.
    2. 2つの異なるファイル記述子は、同じオープンファイルハンドルを指すと、同じファイルオフセット量を共有します.したがって、どちらかのファイル記述子によってファイルオフセット量(read()、write()またはlseek()が呼び出された場合)を変更すると、両方のファイル記述子が異なるプロセスに属しているかどうかにかかわらず、同じプロセスに属しているかどうかにかかわらず、別の記述子から変化が観察されます.
    3. 開いているファイルフラグ(O_APPEND、O_NONBLOCK、O_ASYNCなど)を取得および変更するには、fcntl()のF_GETFLとF_SETFLオペレーションは、役割ドメインに対する制約が前のものと似ています.
    4. ファイル記述子フラグ(close-on-exec)は、プロセスおよびファイル記述子にプライベートです.このフラグの変更は、同じプロセスまたは異なるプロセスの他のファイル記述子には影響しません.
 
この文書は次のとおりです.http://blog.csdn.net/cywosp/article/details/38965239