ファイル記述子(ファイルきじゅつし、英語: file descriptor)とは、コンピュータプログラミングにおいてファイルへの参照を抽象化したキーである。ファイルディスクリプタ/ファイルデスクリプタ[1][2]あるいはFDとも呼ばれる。UNIX系システムでテキストターミナルを含むファイルストリームを参照する際に用いられる。
MS-DOS[3]やMicrosoft Windowsでは、「ファイルハンドル」がほぼ相当するが、技術的には異なるオブジェクトである。
POSIXでは、ファイル記述子は整数型の値であり、詳述すればC言語のint
型である。POSIXでは、全てのプロセスが持つべき3つのファイル記述子を定義している(デーモンなどはその限りではない)。
整数値 | 名前 |
---|---|
0 | 標準入力 (stdin) |
1 | 標準出力 (stdout) |
2 | 標準エラー出力 (stderr) |
一般にファイル記述子は、オープン中のファイルの詳細を記録するカーネル内データ構造(配列)へのインデックスである。POSIXでは、これをファイル記述子テーブルと呼び、各プロセスが自身のファイル記述子テーブルを持つ。ユーザーアプリケーションは抽象キー(=ファイル記述子)をシステムコール経由でカーネルに渡し、カーネルはそのキーに対応するファイルにアクセスする。アプリケーション自身はファイル記述子テーブルを直接読み書きできない。
UNIX系システムでは、ファイル記述子がファイルだけでなく、ディレクトリ、ブロックデバイスやキャラクターデバイス(スペシャルファイルとも呼ぶ)、ソケット、FIFO(名前付きパイプ)、名前なしパイプなどのカーネルオブジェクトを汎用的に参照するのに使われる。
標準Cライブラリの、FILE
型(ライブラリが管理するデータ構造)へのポインタ(FILE *
)があらわすものをストリームと言い[注釈 1]、POSIXではファイル記述子とストリームを包括する用語として「ハンドル」を使っている(参考: "Interaction of File Descriptors and Standard I/O Streams"[要文献特定詳細情報])[注釈 2]。『プログラミング言語C』第2版ではFILE *
を「ファイル・ポインタ」と呼んでいる。原著『The C Programming Language』では「file pointer」と呼んでいる。FILE
型の実装は規格で規定されておらず、オブジェクト型(object type)[注釈 3]であることのみが規定されているが、通例構造体であり、UNIX系システムでは一般に低レベルのファイル記述子を含んでいる。これらはプラットフォームではなくプログラミング言語によって標準化された上位層のコンセプトであるため、ファイル記述子と同一視はできない。
Javaの標準クラスライブラリには、ファイル記述子を表現するハンドルとしてjava.io.FileDescriptor
があり、主にjava.io.FileInputStream
またはjava.io.FileOutputStream
を作成するために使用される。
Microsoft Windowsカーネルでは、ファイル記述子と同様であるが、より汎用的な機構によりファイルオブジェクトを含むさまざまなカーネルオブジェクトを「ハンドル」という抽象的な識別子に関連づける枠組みが採用されている。特にファイルを表すカーネルオブジェクトに関連づけられたハンドルを「ファイルハンドル」と呼ぶが、これはPOSIXにおけるファイル記述子とほぼ同等の役割を担うものと解釈することができる。このファイルハンドルは、前述の(ファイル)ハンドル[どれ?]とは異なるものを指すが、同一の語のため、混乱を生じることがある。MS-DOSではファイル記述子ほぼそのものを指して「ファイルハンドル」と呼んでいた。
マイクロソフトのCランタイムライブラリ (CRT) は、C標準I/Oライブラリとは別に、POSIX互換関数群として、オペレーティングシステムにおけるネイティブのファイルハンドルとPOSIX的な整数のファイル記述子を相互変換して扱える機能を持っている[4][5]。
最近[いつ?]のUNIX系システムが提供するファイル記述子関連の操作(システムコールとライブラリ関数)は以下の通りである。
UNIXのファイル記述子は、一種のケイパビリティである。sendmsg() システムコールを使うとプロセス間でファイル記述子をやり取りすることができる。つまり、UNIXのプロセスが持つファイル記述子テーブルは「ケイパビリティリスト (C-list)」の実例と見ることもできる。