システムコールを選択する最初の引数の目的は何ですか?


25

から man select

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

nfdsは、3つのセットのいずれかで最も大きい番号のファイル記述子に1を加えたものです。

ファイル記述子を決定できる、およびnfdsをすでに持っている場合、の目的は何ですか?readfdswritefdsexceptfds


私はSOについて尋ねようとしていましたが、ここではより集中化されており、C API呼び出しはon-topicと見なされます
プネヘヘ

回答:


25

、「UNIX環境での高度なプログラミング」、W.リチャードスティーヴンスは、それがパフォーマンスの最適化であると言います。

カーネルは、関心のある最高の記述子を指定することで、3つの記述子セットの何百もの未使用ビットを調べて、オンになっているビットを探すことを回避できます。

(第1版、399ページ)

UNIXシステムのプログラミングを行う場合は、APUEブックを強くお勧めします。


更新

アンは、fd_set通常、1024のファイルディスクリプタまで追跡することができます。

どれfdsが設定され0、どれが設定される1かを追跡する最も効率的な方法はfd_setビットセットであるため、それぞれが1024ビットで構成されます。

32ビットシステムでは、long int(または「ワード」)は32ビットであるため、それぞれfd_set
1024/32 = 32ワードであることを意味します。

nfds多くのアプリケーションで使用される8や16などの小さなものの場合、最初の単語の内側を見るだけで済み、32個すべての内側を見るよりも明らかに速いはずです。

(参照FD_SETSIZEして__NFDBITSから、/usr/include/sys/select.hご使用のプラットフォーム上の値のため。)


更新2

関数シグネチャがそうではない理由について

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

私の推測では、コードはすべての引数をレジスタに保持しようとするため、CPUはそれらをより速く処理でき、余分な2つの変数を追跡する必要がある場合、CPUには十分なレジスタがない可能性があります。

つまり、select実装の詳細を公開することで、より高速になります。


2
それ、またはより最近のThe Linux Programming Interface
chris

APUEも最近更新されました。第2版​​:amazon.com/gp/aw/d.html/ref=aw_d_detail
Mikel

@chris Linuxプログラミングインターフェイスを確認します。ありがとう。
ミケル

情報をありがとう、私は私がしばらくつかむときに本をチェックします。
プネヘヘ

APUE 2nd Ed:2005年6月27日(linux-2.4.22をカバー)TLPI:2010年10月(linux-2.6.35をカバー)
chris

6

私はselect()の設計者ではないので、よくわかりませんが、パフォーマンスの最適化だと思います。呼び出し関数は、読み取り、書き込み、およびFDを除くファイル記述子の数を知っているのに、なぜカーネルがそれを再び把握する必要があるのでしょうか?

80年代前半にselect()が導入されたとき、それらには動作するマルチギガヘルツ、マルチプロセッサがなかったことを思い出してください。25 MHz VAXは非常に高速でした。さらに、可能であればselect()を高速で動作させたいと考えていました。プロセスを待機しているI / Oがある場合、なぜプロセスを待機させるのですか?


あなたの議論には、ただ1つではなく、必要nreadfdsnwritefdsと言うでしょう。nexceptfdsnfds
プネヘヘ

たぶんそれnfdsは、より高速なアクセスのためにレジスターに入れられるようにするためです。他のすべての引数とともに3つの数値を追跡する必要がある場合、CPUに十分なレジスタがない可能性があります。もちろん、カーネルはnfds仮想の3つの変数に基づいて独自に作成することもできます。したがって、効率を高めるために実装の詳細を公開しているのではないかと思います。
ミケル

@Mikel、phunehehe:別々のnfds引数はほとんど利益をもたらさないでしょう。ほとんどの場合、プロセスはに比べて非常に少ないプロセスを開いていFD_SETSIZEます。典型的なケースでは、1024のうち(4,4,2)があります。カーネルチェック(4,4,4)を行うことは(1024,1024,1024)に対する大きな勝利ですが、(4,4,2)までの最適化はほとんど役に立ちません。
ジル 'SO-悪であるのをやめる'

@Gilles:ゲインはよりクリーンなAPIになります。(現状では、プログラマーは計算のために余分な作業を行うか、nfds遅延してを呼び出すselect(FD_SETSIZE, ...)必要があります。これは、より遅くなります。)
Mikel

OTOH、最大変数を1つだけ追跡することは、プログラマにとっても簡単です。
ミケル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.