ファイルディスクリプタって何?仕組みとWindowsのC言語、Linuxでの上限

プログラミング
スポンサーリンク

ファイルディスクリプタ(File descriptor)は、日本語ではファイル記述子とも呼ばれるようです。

プログラミングの世界では、単にFDと省略されることもあります。

ファイルディスプリプタって何なんでしょうか?

スポンサーリンク

ファイルディスクリプタとは?仕組みと枯渇、解放

ファイルディスクリプタとは、0から始まる整数の識別子です。

ファイルディスクリプタとは、プログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子。0から順番に整数の値が割り当てられる。OSによってはファイルディスクリプタにバッファ管理機能なども含めた「ファイルハンドル」と呼ばれる管理体系が存在する。

ファイルディスクリプタには、識別子とともにファイル名、ファイルサイズ、プログラムが操作中のファイル内の位置、ファイル作成、更新日時などの情報が含まれており、OSは識別子によってどのファイルを操作するかを判断する。

通常、0:標準入力(stdin)、1:標準出力(stdout)、2:標準エラー出力(stderr)の3つはOS(シェル)が最初に用意するため、プログラムがファイルをオープンすると「3」から順番にディスクリプタが割り当てられる。

http://e-words.jp/w/ファイルディスクリプタ.html

 

0 = stdin

1 = stdout

2 = stderr

というのは大事なので覚えておきましょう。

 

以下の記事にもまとめています。

標準出力と標準エラー出力 (stderr) へコマンドプロンプトにてリダイレクト、パイプの使い方
標準出力と標準エラー (stderr) へコマンドプロンプトでリダイレクト、パイプの使い方をまとめてみました。 標準出力と標準エラー出力を同時に(または別ファイルに)リダイレクトする方法も調べてみました。 標準ストリーム(Standa...

 

プログラムがファイルをオープンすると「3」から順番にディスクリプタが増えて割り当てられます。

一つのプロセスがファイルオープン可能な上限を超えて、ファイルディスクリプタが枯渇した場合、エラーが出てそれ以上はオープンできなくなります。

よって、プロセス内でファイルディスクリプタが不要になった場合は、解放漏れがないように制御する必要があります。

 

Visual Studioでは、stdio.hで以下のように定義されているらしい。

 

MSDNに以下のサンプルプログラムが載っていました。

 

実行結果は次の通りです。

The file descriptor for stdin is 0
The file descriptor for stdout is 1
The file descriptor for stderr is 2

Windowsのファイルディスクリプタ(ファイルハンドル)とC言語、上限

Microsoft Windowsの世界ではファイルディスクリプタは、ファイルハンドルと呼ばれることがあります。

Windowsでは、1プロセスあたり255*255*255=16581375個のハンドルが上限です。

 

ただ、Visual Studioなどを使ってC言語のライブラリ関数を使うと、ライブラリの仕様により上限が変わるようです。

16581375個のファイルがオープンできる訳ではありません。

マイクロソフトのMSDNの公式ドキュメントには以下のように記述されていました。

C ランタイム ライブラリには、同時に開くことのできるファイル数の上限が 512 に設定されています。 上限を超える数のファイル記述子またはファイル ストリームを開こうとすると、プログラム エラーが発生します。

上限のファイル数を変更するには、_setmaxstdio を使用します。

 

上限を超える、多くのファイルをオープンすると「Too Many Open Files」のような警告が出るようです。

Linuxのファイルディスクリプタの上限、確認

 

Linuxの場合、ファイルディスクリプタの上限の確認は、ulimit コマンドを使って行います。

 

 

ulimit -n を使って、一時的に制限を変更することが可能です。

ただし、システムを再起動すると元に戻ってしまいます。

 

よって、永続的に制限を変更するには、

/etc/security/limits.conf の設定を書き変え、制限を変更するようにします。

 

全てのユーザー(*)のプロセスが使えるファイルディスクリプタ(nofile)のsoft(ユーザーが設定できる)とhard(rootが設定できる)上限を共に64000にするには、以下のように設定します。

/etc/security/limits.conf

 

ちなみに、Linuxでファイルディスクリプタの上限を超えて一つのプロセス内で多くのファイルオープンをすると、次のようなエラーが起きます。

cannot make pipe for process substitution: Too many open files

 

コメント