21

私は最近かなりの量のファイル記述子を使用してきましたが、なぜそれらが整数として実装されているのか疑問に思っていました。

これは、それらが他の整数と混同しやすいことを意味し、それらが何であるか、それらが何を指しているのか、それらが開いているかどうかなどをコンテキストなしで知る方法はありません.

C ではFILE、不透明struct型です。多くの人は、typedefたとえばstatus_t整数としても機能するため、その機能は明らかです。最善の方法は、それらを不透明な型として実装するか、(C++ などで) 実装の一部を処理できるクラスとして実装し、少しクリーンアップすることです ( ornamespaceの呼び出しは非常に無害に思えます)。 、コンテキストなしでパイプまたは開いているものは明らかではありません)。たとえば、パイプを作成したりファイルを開いたりするためのコンストラクター/ファクトリー関数など。pipe()open()std::file_descriptor

これがこのサイトの話題になることを願っています。「なぜこの特定の決定が下されたのですか? 」と表現しようとしましたが、それがより適切な場所を誰かが知っている場合は、教えてください.

4

3 に答える 3

27

他に何もなければ、歴史。1970 年代には、単に使用することはおそらく問題には思えませんでしたint(実際、値は固定サイズのテーブルへのインデックスでした)。後で別の型に変更すると、コードが壊れてしまいます。

于 2013-07-22T13:18:56.227 に答える
19

あなたの質問は2つに分けることができます:

POSIX ファイル記述子はなぜintですか?

すでに確立されたツールやライブラリのほとんどのものと同様に、答えはおそらく歴史的な理由です。ジェームズの答えはこれを指摘しています。

ファイル記述子を不透明にすることはおそらく良い考えですが、あなたが言及した理由ではありません。型を不透明にすることは、いくつかのパラメーターに基づいて異なる型を持つのに適しています。たとえば、一部のシステムではlong longas ファイル記述子が必要な場合があります。しかし、実際には、20 億個のファイルを同時に開いている必要がある人はどこにもいないため、この存在しない問題を修正しようとする人は誰もいません。

一方、typedef int file_descriptor;上記の問題のいずれも修正されないようなもの:

これは、他の整数と混同しやすいことを意味します...

変数を混同している場合は、悪いニュースがあります。file_descriptorとは同じ型であるため、コンパイラはどちらも役に立ちませんint。したがって、一方に対する操作はもう一方に対して許可されます。

...そして、それらが何であるか、それらが何を指しているのか、それらが開いているかどうかなどをコンテキストなしで知る方法はありません.

どちらでもそれを行うことはできませんFILE。のように、求める情報を照会して返す関数があるのはそのためですFILEtypedefタイプを ing しても、追加情報は得られません。

POSIX に C++ ラッパーがないのはなぜですか?

要するに、Microsoft を除いて、C++ に熱中するオペレーティング システム開発者はいないからです。Windows はかろうじて POSIX でさえあるため、Microsoft が POSIX を改善しようとする望みはありません。POSIX準拠の他のオペレーティングシステムには、事実上のシステムプログラミング言語としてC APIがあります(nmが言うように、ほとんどすべての言語がCにバインドできるためです)。

実際、C++ はアプリケーション開発者の間では人気がありますが、システム プログラマーの間ではそれほど人気が​​ありません。POSIX 委員会も特に C++ には関心がないようです。そのため、POSIX API に関して C と C のみのソリューションと引数が表示されます。また、 POSIX は特に UNIX のインターフェイスを標準化するために作成されたことにも注意してください。これは C で記述されており、その最も重要な子孫の 1 つである Linux も C に強く結び付けられています。

于 2013-07-22T14:49:28.067 に答える
2

Unix インターフェイスは C 言語で説明されていますが、システムが API だけでなく ABI を備えていることも同様に重要です。

プログラミング言語に特有の複雑なデータ構造は、ABI を複雑にします。ABI レベルでは、「32 ビット符号なし整数」などの低レベルのデータ型とその単純な集計しかありません。

そうは言っても、Unix インターフェースは などの型を使用するpid_tので、ファイル記述子にこれらの typedef の 1 つを使用しないのはなぜでしょうか?

ファイル記述子には特定の既知の値があり、新しいファイル記述子が開かれると、利用可能な最小の正の値が常に使用されます。ファイル記述子の値は、記述子のテーブルへの配列インデックスとして効果的に機能し、意図的にそのように設計されています。ファイル記述子のプログラマーのモデルは、カーネル内にそれらの配列のような構造があるというものです。このdup2関数は、ファイル記述子をあるスロットから別のスロットに実際に複製できます。このような配列インデックスは である可能性がありint、信号エラーの場合は負の値になります。

C の typedef は追加の型チェックを購入しませんが、読みやすさと抽象化 (特定の整数型からの独立性) をもたらします。fd_tタイプは、intあるシステムでは であり、別のシステムでは である可能性がありlongます。しかし、int数十年前にほぼどこでも 32 ビット幅に成長して以来、同じ名前でより広くできるようにするために抽象化する必要はありません。プログラムが 20 億を超えるオープン ファイル記述子を必要とすることは非常にまれです。

対照的にint、例えばpthread_t.

int記述子は、Windows ソケット API の設計者にとって飲み込むのが難しいことが判明しました。型定義を発明したのはSOCKET、その値が利用可能な最小の正の整数ではないためです。移植性の煩わしさにつながる癖の 1 つにすぎません。ただし、これらの記述子が範囲内の小さな値であることに依存するコードは、機能しないか、非効率的に動作するという点で、実際の意味上の違いがあります。

Unix が改訂されて単純なint型が何らかの typedef に置き換えられた歴史的な例があります。たとえば、accept関数では、リモート アドレス構造体のサイズは以前はちょうどint. すると になりましsocklen_tた。が存在する技術的な必要はありませんsocklen_tintこれは、従来のシステムを使用するシステムと、メンテナーが使用する引数を熱心に変更したシステムとの間の違いを橋渡しするための一時的な解決策として発明されましたsize_tsize_tこれら 2 つのタイプは同じ ABI につながりましたが、64 ビットと 32 ビットのシステムになるまで問題はありませんでしintた。

于 2013-07-22T18:51:27.567 に答える