Chapter 3. Sambaアーキテクチャ

Dan Shearer

November 1997

Table of Contents

概要
マルチスレッドとSamba
smbdのスレッド化
nmbdのスレッド化
nbmdのデザイン

概要

この文書は、内部的にSambaがどのように動くかについての一般的な概要を説明している。 Samba Teamは、非常に汚いSMBとCIFSプロトコルによって押しつけられる、優雅さ、セキュリティと 制約の間で、最も良い妥協点であるモデルを見いだそうとした。

また、以下のようなよく聞かれる質問のいくつかに答えようともしている:

  1. UNIX上で動かすときにSambaは安全か?xyzプラットフォームでは? root特権についての問題は?

  2. Sambaのいくつかの部分中でのマルチスレッドの賛否

  3. なぜ、名前解決、WINSとブラウジングに関して分離されたプロセスがあるのか?

マルチスレッドとSamba

人々は時々、一様にスレッドを良いものとして推奨する。それらは推奨する人にとっては とても良いものであるが、smbdに取ってはまったく不適当である。nmbdは別の問題で、 マルチスレッドそれ自身はとても良いことである。

手短に言うと、smbdはマルチスレッド化されておらず、UNIX配下での別のサーバー(例えば、 書いている時点においてはSyntax)はこの方法を取っていて、とても大きな性能上の問題を 抱えていて、頑丈ではない。nmbdもスレッド化されていないが、これは、35以上もの プラットフォームにまたがって、コードの整合性を取り、ポータブルにするということが、 不可能だからという理由である(この欠点は同じくsmbdをスレッド化することにも当てはまる)。

より長い期間において、smbdをマルチスレッドにしない、とても良い理由が存在している。 マルチスレッドはSambaをより遅くし、スケーラビリティを減少させ、移植性をなくし、 とても不安定にさせる。実際、各接続に対して独立したプロセスを使用していて、それは Sambaの最も大きな利点の1つである。

smbdのスレッド化

スレッド化したsmbdから発生するいくつかの問題は以下の通り:

  1. プロセスの代わりにスレッドを作成するだけでなく、スレッド固有で存在しなければならない 場合、すべての変数について管理を行わなければならない(現在それらはグローバルである)。

  2. もしもある1つのスレッドが異常終了すると(例えば、セグメンテーションフォルト)、 すべてのスレッドが異常終了する。信頼性を損ねることになる。

  3. 使用している多くのシステムコールがブロックしている。多くのシステムコールで ブロックしないか同等のことをするものは、用意されていないか、うまく使えない (そして遅い)。そのため、ある1つのスレッドでブロックしている間は、すべての クライアントは待たされることになる。ある共有が遅いNFSファイルシステムで、 その他が早いものだと仮定してみた場合、すべてのクライアントが、NFSのスピードに 抑制されてしまう。

  4. 異なったスレッド中で異なったuidとして動作できない。これは、すべてのSMBパケット上で uid/gidをスイッチしなければならないと言うことを意味する。それはとてつもなく遅い。

  5. プロセスあたりのファイルディスクリプタ制限は、制限されたクライアントの数のみを サポートできることを意味する。

  6. プロセスに対してfcntl()のコンテキストでロッキングを行うようにスレッドに対して システムロッキングを使うことが出来ない。

nmbdのスレッド化

これは理想ではあるが、ポータビリティの要求により実現するのは難しい。

Andrew はANSI-Cの範囲のみを使って(setjmpとlongjmpを使って)nmbd用のテスト用 スレッドライブラリを加工とした。残念なことに、いくつかのOSでは、スタック上の 現在のアドレスよりも浅い位置のアドレスを呼び出すためにlongjmpを制限することに よって、うまくいかなかった(見たところでは、AIXがそうである)。これは、真に ポータブルなスレッドライブラリを不可能にしている。そのため、現在対応している すべてのプラットフォームに対して、nmbdのコードをスレッドあり、なしの両方用意 しなければならず、スレッドの本来の目的はコードをきれいにすることであるが、 それを得られない(スレッドが物事を早くするというのは神話である。スレッドは 再帰のようなものであり、物事をきれいにするが、他の何らかの方法によって、いつでも それはもっと早くすることもできる)。

Chrisは、スレッド対独立したプロセス(対他の方法?)を要約する汎用的なデザインを設計 しようとし、いくつかの汎用APCを通して、それらをアクセス可能にした。これは、 プロトコルによるデータ共有要求(現在のパケットに将来のパケットが依存するなど)という 理由でうまく動かなかった。少なくとも、コードは動いたが、非常にぎこちなく、 その上、fork()タイプモデルは、UNIX上では決して動かなかった(nmbdに対して、 それが動くOSはあるのだろうか?)。

fork()は安っぽいが、受信したすべてのUDPパケット上で処理を行うのに、十分 安っぽいわけではない。プロセスのプールを持つことは可能であるが、プロセス間で、 (複雑な構造体中で)共有された巨大な量のデータのために、プログラムをきれいにする ことは、ひどく難しい。各プラットフォームが共有メモリシステムを持つ事を あてにすることは出来ない。

nbmdのデザイン

もともと、Andrewは、途方もなくスタックを使い、全くもってデバッグ作業を混乱させる、 マルチスレッド環境をシミュレートするための再帰を使った。Luke Leightonは各パケット上で ステート情報を保持する問い合わせシステムを使うように書き直した。最初のバージョンは、 すべての待機状態ステートによって使われる単一の構造を使っていた。この構造の初期化は、 引数を追加することで行われ、機能が開発するに従い、だんだん複雑化していった。 そのため、より高位の関数と、ユーザーが定義したメモリブロックを指定するポインターによって 置き換えられた。これは突然物事をより簡単にした:非常に多数の関数は静的に作成され、 モジュール化された。これはNTカーネルで使われているものと同じ原理であり、単一の プロセス中ではあるが、スレッドと同じような効果が成し遂げられた。

次に、Jeremyはnmbdを書き直した。nmbd中のパケットデータはネットワーク上のものではない。 この形式は、処理に対してとても従順なものであるが、まだ他のパケットの内容を保持していた。 nameserv.h中の"struct packet_struct"を参照のこと。そこにはすべての詳細があるが、 ネットワーク上のメッセージについては記述がない。これは、ブラウジングとWINSサポートの ための、ディスクかメモリベースのデータベース中で理想的に使えるようにする。