Path: sran265!katsu From: katsu@sran14.sra.co.jp (WATANABE katsuhiro) Message-ID: Date: 11 Jan 93 09:49:58 Organization: Software Research Associates, Inc.,Japan In-reply-to: ryu@sushi.goldman.co.jp's message of 10 Dec 92 06:14:40 GMT Newsgroups: fj.sys.sun,fj.sys.news Subject: Re: open 257 files in a process (Re: Open file par process) Distribution: fj References: (Newsgroups: に注意)  フォローの遅さなら *.jp で十指にはいるであろう渡邊@SRAです。  オープンできるファイルの数を増やすために limit をいじる件についてです。  limit descriptors(RLIMIT_NOFILE) は SunOS 4.1 から導入されたものだと 思いますが、NEWS-OS でも R4.2 からこれが導入されたようですね。  limit を使いこなすには、当然ながら対象となっている資源の知識が 必要です。フォローにあった limit(1) や csh(1) はもちろん、 setrlimit(2) の類も、この点では役に立つとは思えません。 記事 で ryu@sushi.goldman.co.jp (Masahiro Yanagisawa) さんいはく > 少し前に limit で 1プロセスがopenできる数を 256 に増やすという > お話がありましたよね。 > 私も興味を持ったんですが、 > csh> limit > descriptors 64 > この64っていう数字は何処でデフォルト設定されるんでしょう? > パラメータを変えて reconfig してみたんですが、 > 64, 256 というデフォルトに変化は無いようでした。  /vmunix の main() で swapper(process 0) を作るときに設定され、これが 継承されていくようです。(NEWS-OS 4.2 も同じ)  一部で信じられているような、init が設定するとか、kernel が init に 対して設定するというのは誤りだと思います。  この値が気に入らなければ、reconfig などでは変更できないので、 /vmunix のバイナリにパッチを当てることになります。(制限を強める 方向は簡単です。しかし数を増やす方向も簡単かどうかは不明です。) (ついでながら、descriptors 以外の limit はどこで設定されるかという 疑問が当然わきおこることでしょう。NEWS-OS の 場合、main() で process 0 に対する limit が一旦全て RLIMIT_INFINITY に設定され、 さらに stacksize, memoryuse, memoryuse 等が vminit() で適当に 再設定されるようです。Sun OS ではどうなのかは知りません。詳しい方 教えて下さい。)  reconfig では変更が反映されない件は別の記事 で説明しておきました。  カーネルのソース上でどのように 64 というのが表現されているかという 問題ならば、NOFILE_IN_U を参照すると想像しています。hard limit の 方は NOFILE ではないでしょうか。もちろんこうした詮索は我々ユーザーには あまり意味がないかもしれません。 > csh> limit descriptors 256 は出来ても、 > csh> limit descriptors 257 は > limit: descriptors: Can't set limit > となってしまいます。  ここで、"Can't set limit" という警告が出たのは、hard limit を越えて 設定しようとしたからに過ぎないと思います。  では limit -h 等で hard limit の方を 256 より大きくできるかというと、 できません。setrlimit(2) システムコール内で、descriptor の hard limit を 256 より大きく設定しようとしたときは、256 に設定して しまうようになっているからです。(NEWS-OS 4.2 でも同じ)  そもそも、SunOS および NEWS-OS の以前のバージョンや、これらの 源流である 4.3BSD には、descriptors のlimit がありませんでした。 (NET-2 release 等についてはわかりません。)プロセスごとの descriptorは、 u area 内の u.u_ofile[NOFILE] という *固定長* の配列にとられており、 そもそも descriptor の資源を制限することに意味がなかったのです。  さて、UNIX が広まるうち、ファイルを沢山 open する大規模な アプリケーションが出現して、この配列を拡張する必要が生じるように なったのでしょう。ところが、カーネル用のスタック領域を圧迫しないよう、 user 構造体は小さいことが望まれています。それなのに、どれだけ使われるか わからない descriptors 用に普段から大きな領域を取ってしまうのは 感心しません。というわけで、大きな固定領域を確保するのではなく、 動的に割り当てることが考えられたものと思います。  こうして *動的に変化* するようになったことで、はじめて descriptor の limit の意味が生まれたのではないでしょうか。  ついでに、現在の実装での特徴をいくつか明らかにしておきます。 [1] descriptor table の動的な割り当ての方法  オープンしているファイルの descriptor の最大の番号 u.u_lastfile が 64 未満の時は旧来どおり u area 内にテーブルがあります。64 以上に なるときにはじめて動的な割り当てが起こり、u area の外部(カーネルの データ領域)にテーブルが置かれるようになります。(SunOS, NEWS-OS 両方とも)  descriptors の soft limit が普段は 64 であるのも、適当な数を 恣意的に持ってきたわけではなく、こうした理由によるものでしょう。 ちなみに、このような不連続な扱いを受けている理由ですが………… #ifdef 想像  descriptor table は本来なら u area 内にあるべきもので、swap out されるべきものですが、動的に割り当てた descriptor 用の領域も swap out しなければならないでしょうか?もちろんこれは面倒なので swap out したくありませんが、システム内で動いているプロセス全部の descriptor table が常駐するのも好ましくないでしょう。そこで、 descriptor を 64 個以下しか使わない大部分のプロセスは従来どおり u area にテーブルを確保し、沢山の descriptors を使うような一部の プロセスについてのみ、テーブルをカーネルのデータ領域に抱え込む ようにするという現在の戦略が選択されたのではないでしょうか?  しかし、もしかしたら、後で述べるようなバイナリ互換性の問題に すぎないかもしれません。 #endif /* 想像 */  SUN OS 4.1 以降の場合は u.u_lastfile が一旦 64 以上になると、 以降はよしんば 64 未満に戻ることがあっても、プロセスが生き残る限り 動的に割り当てられた領域が使い続けられます。一方 NEWS-OS 4.2 の場合、 64 未満に戻ることがあれば、再び u area 内の領域が使われます。 [2] 割り当ての単位  動的に割り当てるとはいえ、64 番以上の descriptor を作るときに 一度に 256 個分を割り当ててしまう実装になっています。(SunOS, NEWS-OS 両方とも)  つまり、limit descriptors 64 または 256 だけが他にくらべて特別な 意味を持つことになります。  64, 256 以外の半端な数への設定でも、システムファイルテーブルを 単一のプロセスで使い果たしにくくなる効果があるという主張もあるかも しれません。しかし、システムのオープンファイル構造体とプロセス内の descriptor が本来は1対1には対応しないことを鑑みると、これはやはり 偶然の副作用に過ぎないと私は考えています。 [3] バイナリ互換性の保持のための処置  テーブルを拡張するためには普通に考えると user 構造体の変更をする ことになりますが、これは広い範囲に影響が及び、なかんずくバイナリーの 互換性への影響(core ファイル、ps, pstat, adb, dbx 他が影響を受ける) は厄介な問題となってしまうことでしょう。  SunOS も NEWS-OS も、この問題はうまく回避されています。 (a) NEWS-OS の場合  NEWS-OS 4.2 の には、バイナリ互換性を意識した旨の コメントがついています。  u area 内の descriptor table である u.u_ofile の大きさや位置は 変更せず、拡張分である動的に確保したテーブルへのポインタは u area の終端に配置することで、4.1 以前との間のバイナリ互換性を 保つようにしてあるようです。 (b) SunOS の場合  なんと、SUN OS 4.0.x の時から NOFILE を大きくする時のことを考えて、 すでに user 構造体だけは先んじて拡張が施され、将来のバージョンとの間の バイナリ互換性に備えるようになっていました。  4.0.x の には、kmem を参照するコマンドの、(4.0.x から 見れば)将来におけるバイナリー互換性についてのコメントがついていた ものでした。 -- 渡邊克宏@SRAソフトウェア工学研究所