ファイル記述子とは
ファイル記述子(file descriptor)は、
コンピュータプログラミングにおいて、ファイルやソケットなどの
カーネルオブジェクトへの参照を抽象化したキーです。ファイルディスクリプタやFDとも呼ばれます。
UNIX系システムで、テキストターミナルを含むファイルストリームを参照する際に用いられます。
MS-DOSや
Microsoft Windowsでは、「ファイル
ハンドル」がほぼ相当する概念ですが、技術的には異なるオブジェクトです。
概要
POSIXでは、ファイル記述子は
整数型の値(
C言語の`int`型)で表現されます。全ての
プロセスは、標準入力、標準出力、標準エラー出力に対応する3つのファイル記述子を必ず持ちます(デーモン
プロセスなどは例外)。
一般にファイル記述子は、オープン中のファイルの詳細を記録する
カーネル内のデータ構造(
配列)へのインデックスとして機能します。POSIXでは、このデータ構造をファイル記述子テーブルと呼び、各
プロセスが独自のファイル記述子テーブルを持ちます。ユーザーアプリケーションは、ファイル記述子をシステムコール経由で
カーネルに渡し、
カーネルがそのキーに対応するファイルにアクセスします。アプリケーションはファイル記述子テーブルを直接読み書きできません。
UNIX系システムでは、ファイル記述子はファイルだけでなく、
ディレクトリ、ブロックデバイス、キャラクターデバイス(スペシャルファイル)、ソケット、FIFO(名前付きパイプ)、名前なしパイプなど、様々な
カーネルオブジェクトを汎用的に参照するために使用されます。
標準C
ライブラリの`FILE`型(
ライブラリが管理するデータ構造)へのポインタ(`FILE
`)が表すストリームは、POSIXではファイル記述子とストリームを包括する用語として「ハンドル」を用いています。`FILE `は「ファイル・ポインタ」とも呼ばれます。`FILE`型の実装は規格で規定されておらず、オブジェクト型であることのみが規定されていますが、通例構造体であり、
UNIX系システムでは一般に低レベルのファイル記述子を含んでいます。これらはプラットフォームではなく、プログラミング言語によって標準化された上位層の概念であるため、ファイル記述子と同一視することはできません。
Javaの標準クラス
ライブラリには、ファイル記述子を表現する
ハンドルとして`java.io.FileDescriptor`があり、主に`java.io.FileInputStream`や`java.io.FileOutputStream`を作成するために使用されます。
Microsoft Windowsカーネルでは、ファイル記述子と同様の役割を果たす「
ハンドル」という抽象的な識別子が用いられます。ファイルオブジェクトを含む様々な
カーネルオブジェクトを
ハンドルに関連付けます。特に、ファイルを表す
カーネルオブジェクトに関連付けられた
ハンドルは「ファイル
ハンドル」と呼ばれ、POSIXにおけるファイル記述子とほぼ同等の役割を果たします。
MS-DOSでは、ファイル記述子ほぼそのものを指して「ファイル
ハンドル」と呼んでいました。
マイクロソフトのCランタイム
ライブラリ(CRT)は、C標準I/O
ライブラリとは別に、POSIX互換関数群として、
オペレーティングシステムにおけるネイティブのファイル
ハンドルとPOSIX的な整数のファイル記述子を相互変換して扱える機能を提供しています。
ファイル記述子に関する操作
最近の
UNIX系システムが提供するファイル記述子関連の操作(システムコールと
ライブラリ関数)は以下の通りです。
ファイル記述子の生成
`open(), open64(), creat(), creat64()`: ファイルをオープンまたは作成し、対応するファイル記述子を取得します。
`socket()`: ソケットを作成し、対応するファイル記述子を取得します。
`socketpair()`: ペアのソケットを作成し、対応するファイル記述子を取得します。
`pipe()`: パイプを作成し、読み込み用と書き込み用のファイル記述子を取得します。
1つのファイル記述子に関する操作
`read(), write()`: ファイルからの読み込み、ファイルへの書き込みを行います。
`recv(), send()`: ソケットからの受信、ソケットへの送信を行います。
`recvmsg(), sendmsg()`: メッセージの受信、送信を行います。
`sendfile()`: ファイルの内容を別のファイル記述子に効率的に転送します。
`lseek(), lseek64()`: ファイルの読み書き位置を移動します。
`fstat(), fstat64()`: ファイルの情報を取得します。
`ftruncate()`: ファイルのサイズを切り詰めます。
`fchmod()`: ファイルのアクセス権を変更します。
`fchown()`: ファイルの所有者を変更します。
複数のファイル記述子に関する操作
`select(), pselect()`: 複数のファイル記述子に対するI/Oイベントを監視します。
`poll()`: 複数のファイル記述子に対するI/Oイベントを監視します。
ファイル記述子テーブル上の操作
`close()`: ファイル記述子を閉じます。
`dup()`: ファイル記述子を複製します。
`dup2()`: 指定したファイル記述子を別のファイル記述子に複製します。
`fcntl(F_DUPFD)`: ファイル記述子を複製します。
`fcntl(F_GETFD and F_SETFD)`: ファイル記述子のフラグを取得・設定します。
プロセス状態を変更する操作
`fchdir()`: プロセスのカレントディレクトリを指定されたファイル記述子の示すディレクトリに変更します。
`mmap()`: ファイルの指定された範囲を
プロセスのアドレス空間にマップします。
ファイルロック
`flock()`: ファイルロックを行います。
`fcntl(F_GETLK, F_SETLK and F_SETLKW)`: ファイルロックを行います。
`lockf()`: ファイルロックを行います。
ソケット
`connect()`: ソケットをリモートアドレスに接続します。
`bind()`: ソケットをローカルアドレスにバインドします。
`listen()`: ソケットを接続待ち状態にします。
`accept()`: 接続要求から新たなソケットファイル記述子を生成します。
`getsockname()`: ソケットのローカルアドレスを取得します。
`getpeername()`: ソケットのリモートアドレスを取得します。
`getsockopt(), setsockopt()`: ソケットオプションを取得・設定します。
`shutdown()`: 全二重接続の一方または両方を切断します。
その他
`ioctl()`: 一般にデバイスに対応するファイル記述子に関する様々な操作を行います。
ケイパビリティとしてのファイル記述子
UNIXのファイル記述子は、一種のケイパビリティとして機能します。`sendmsg()` システムコールを使うと、
プロセス間でファイル記述子をやり取りできます。
UNIXの
プロセスが持つファイル記述子テーブルは、「ケイパビリティリスト(C-list)」の実例と見なすことができます。
関連項目
*
ファイル (コンピュータ))