ファイル記述子
ファイル記述子(ファイルきじゅつし、英語: 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
を作成するために使用される。
MS-DOS・Microsoft Windows
編集Microsoft Windowsカーネルでは、ファイル記述子と同様であるが、より汎用的な機構によりファイルオブジェクトを含むさまざまなカーネルオブジェクトを「ハンドル」という抽象的な識別子に関連づける枠組みが採用されている。特にファイルを表すカーネルオブジェクトに関連づけられたハンドルを「ファイルハンドル」と呼ぶが、これはPOSIXにおけるファイル記述子とほぼ同等の役割を担うものと解釈することができる。このファイルハンドルは、前述の(ファイル)ハンドル[どれ?]とは異なるものを指すが、同一の語のため、混乱を生じることがある。MS-DOSではファイル記述子ほぼそのものを指して「ファイルハンドル」と呼んでいた。
マイクロソフトのCランタイムライブラリ (CRT) は、C標準I/Oライブラリとは別に、POSIX互換関数群として、オペレーティングシステムにおけるネイティブのファイルハンドルとPOSIX的な整数のファイル記述子を相互変換して扱える機能を持っている[4][5]。
ファイル記述子に関する操作
編集最近[いつ?]のUNIX系システムが提供するファイル記述子関連の操作(システムコールとライブラリ関数)は以下の通りである。
ファイル記述子の生成
編集- open(), open64(), creat(), creat64()
- socket()
- socketpair()
- pipe()
ひとつのファイル記述子に関する操作
編集- read(), write()
- recv(), send()
- recvmsg(), sendmsg()
- sendfile()
- lseek(), lseek64()
- fstat(), fstat64()
- ftruncate()
- fchmod()
- fchown()
複数のファイル記述子に関する操作
編集- select(), pselect()
- poll()
ファイル記述子テーブル上の操作
編集- close()
- dup()
- dup2()
- fcntl (F_DUPFD)
- fcntl (F_GETFD and F_SETFD)
プロセス状態を変更する操作
編集ファイルロック
編集- 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)」の実例と見ることもできる。
脚注
編集注釈
編集- ^ 「ISO/IEC 9899:1990 §7.9 Input/output」「ISO/IEC 9899:1999 §7.19 Input/output」にそれぞれ対応する「JIS X 3010:1993 §7.9 入出力」「JIS X 3010:2003 §7.19 入出力」の中に「ハンドル」という語はない。
- ^ 他のUNIX系仕様で、NFSなどにファイルハンドルという用語が見られる。
- ^ C言語規格の用語であり、オブジェクト指向プログラミングのオブジェクトとは関係がない。