処理 - みる会図書館


検索対象: UNIX MAGAZINE 2002年1月号
85件見つかりました。

1. UNIX MAGAZINE 2002年1月号

UNIX Communication Notes 山口英 局性能サーバーを目指して ( 3 ) 図 1 トランサクションの構成 十分な処理速度が得られるサーバー このシリーズでは、インターネットにサービスを提供 する高性能なサーバーを構成する技術について解説してい る。 1 回目 ( 2001 年 11 月号 ) で述べたように、高性能 サーバーカえるべき要件は以下の 3 点に集約できる。 クライアント 処理要求 サーバー 処理結果の返送 占郞章に強い。 ・十分な処珊度か得られる。 手間がかからない。 今回は、、、十分な処理速度が得られる " サー する技術をとりあげる。 里とは何か ーを構成 技術そのものの説明に入る前に、サーバーにおける処理 速度について考えてみよう。 インターネットにおける大部分のサーピスは、クライ アント・サーバーモテフレにもとづいておこなわれている。 つまり、サー ーはクライアントからの処理要求を受け 付け、なんらかの処理を施し、結果をクライアントに送 り返す。一般に、クライアントとサーバーとのあいだの やりとりは、、トランザクション (transaction)" と呼はれ る。 WWW システムを例にとると、クライアントからの HTTP GET リクエストの送信と、サーバーから応答と して返されるデータの送受信によって 1 つのトランサク ションカ材冓成される。 トランザクション処理は、大雑把にいえは図 1 のように おこなわれる。ます、クライアントにおいて日該れ 1 にトラ ンサクションが始まる。これが、サーバーには日該れ 2 に届 一一一一一一一一一一一一一いたと - ーしようこの図では、処理要求は 1 バケットになっ UNIX MAGAZINE 2002.1 ているが、複数のバケットから構成される場合もある ) 。 の場合、 t2 ー tl はバケットの伝送遅延を表す。サーバー は処理要求を受け取り、処理をおこなって時刻なに返送 する。すなわち、 t3 ー t2 がサーノヾーでのトランザクション 処王寺間である。そして、日該れ 3 から t4 までのあいだに、 処理結果か数のバケットとしてクライアントに送り返さ れる。トランサクション全体の処理には、 t4 ー tl の時間 がかかっていることになる。 1 つのトランザクション処理は、以下の要素から友さ れる。 1. 処理要求の伝送 2. サーバーでの処理 3. 処理結果の伝送 1 番目と 3 番目は伝送遅延であり、ネットワークの性 能に左右される部分である。 2 番目はサーバーの処理生能 そのものを表す。高性能サーバーを構築するには、この 2 つ、すなわちネットワークでの遅延とサーバー本体での処 理日判りをま可宿する必要がある。 55

2. UNIX MAGAZINE 2002年1月号

連載 /UNIX Communication Notes—O との受信侍ち状態に戻り、もう 1 つのプロセスは処理をお こなうかたちになっていた。これを擬似コードて表現する と、次のようになる。 main() 初期処理 ; socket() ; S bind(s, listen(s) ; while ( 1 ) { / * socket の生成 * / / * s 。 cket に対する設定 * / accept(s, C S exit(O) ; close(cs) ; 実際の処理 ; close(s) ; / * 子プロセス * / if ((pid = fork() / * 受信待ちでプロック このコードからも分かるように、子プロセスがクライア / * 親プロセスは実際に接続されたソケットをクローズ * / / * 受信待ちに戻る * / close(cs) ; システムコールを用いて起動するかたちにした。 inetd に 理するプログラムを inetd が fork() し、さらに exec( 特定のポートへのアクセスがあった場合、そのポートを処 をしなければならない複数のポートを監視する。そして、 inetd は、 select() システムコールを使って、受信待ち UNIX で標準的に使われるようになった。 inetd (lnternet super daemon) が開発され、 4.3BSD せておかなけれはならないという間題を解決するために 上記の間題のうち、あまり使われないデーモンも不力さ inetd の登場 かった。 ・プロセスを複製する fork() システムコールの実行が遅 った。 モリしかなかった衫琪月の UNIX システムには重荷とな として、プロセステープルか増えてしまい、わずかなメ め、デーモンとして稼動させるプロセスか増える。結果 ・ふだん利用しないサーバーもデーモンとして起動けるた この方式には、以 - ドのような間題があった。 のソケット接続要求だけを処理する構造になっている。 ントからの要求を処理し、親プロセスはクライアントから 64 よって起動される処理プログラムは、標準入力からデータ を読み込むと socket に届いたデータを読むことができ、 標準出力に書き出すと相手にデータか送られるような形式 UNIX MAGAZINE 2002.1 グラムのなかでうまく処理できるようにすれはよい。この きなオーバーヘッドをともなう実装ではなく、 1 つのプロ だけに fork() でプロセスを複製している。このように大 さきはど窈疑似コードでは、処理をおこなう部分のため ラムが考案された。 fork() によるプロセスの複製はしないサーバー・プログ 間で通常のデーモン・プログラムとして実行されるが、 その後カーネルに組み込むのではなく、ユーサー空 ユーサー空間で作る ネルに組み込まれることはあまりなかった。 くい。そのため、 NFS 以外のサーバー・プログラムがカー への糾込みは、作業か難しいだけでなく、デバッグもしに しかし、一殳的な処理をおこなうプログラムのカーネル ていた。 ファイルシステムを扱う NFS はカーネルへの実装に適し ロセスの複製というオーバーヘッドを軽減した。しかも、 常駐スレッド (thread) をカーネルに組み込むことで、プ しようと考えたわけである。 NFS では、処理をおこなう るプロセスの複製はしないように実装し、処理性能を改善 変わりはなかった。そこで、常駐はしても、 fork() によ って複製される状況は、 inetd かイ吏われるようになっても サーバーへのアクセスがあるとプロセスが fork() によ これは、 NFS サーバーの実装の際に採られた方法である。 次に考えられたのが kernel resident thread である。 kernel resident thread えなかった。 にデーモンとして起動さ常駐するという形態をとらざるを などの常駐すべきサーバーは、依然としてシステムのプート時 けではない。たとえば、 UDP を用いたサービスや、 sendmail しかし、すべてのデーモンが inetd の管理下に置かれたわ ノート 5 わすかながら改善された。 状態にしておくという間題カ黝夬さシステムの性能が きる。これにより、起動された大量のデーモンを受信待ち peername() などのライプラリ関数を用いて知ることがで の API が定められた。相手のアドレスなどの情報は、 get-

3. UNIX MAGAZINE 2002年1月号

図 3 /etc/exports 列 /usr/local /usr/local /home —maproot=O : 0 —ro —network —network 192. 168. 1 . 0 —mask 255 .255.255.0 192. 168.1 . 0 —mask 255.255.255.0 myp c NFS サーバーの設定 ファイルのロックを別にすると、 NFS サーノヾーでおこ なわれる処理は、以下の 2 つに分かれます。 ・マウント要求の処理 UNIX MAGAZINE 2002.1 デモン、プログラムです。 共有されたファイルに対するロック機溝を寒見するため ・ rpc. lockd の起重丿時の引数で変史できます ) 。 います ( 多くの場合、同時に起重丿けるプロセス数は nfsd 起動され、複数の要求を並列に処理できるようになって れるのに対し、 nfsd は通常 4 ~ 6 個のプロセスか 1 司時に デーモン・プログラムです。 mountd が 1 つだけ起動さ NFS クライアントからのファイル操作要求を処理する ・ nfsd モン・プログラムです。 NFS クライアントからのマウント要求を処理するデー ・ m011 ⅲ d は、名前が異なることもあります ) 。 があります ( これは FreeBSD の場合です。はかの OS で て起動されるデーモン・プログラムには以下のようなもの デーモンがおこないます。これらも含め、 NFS サー ほとんどの OS では、これらの処理はそれぞれ独立した 移動などが含まれます。 操作と同様、読出し、書込み、ファイルの作成・削除・ す。ファイル操作には、ローカルなファイルに対する NFS クライアントからのファイル操作要求を処理しま ・ファイル操作要求の処理 マウントの可否を決定します。 し、あらかじめ設定されたアクセス制御リストに従って ーは NFS クライアントからのマウント要求を処理 レクトリをマウントしなければなりません。 NFS サー 有するためには、ます NFS サーノヾー上の特定のディ NFS クライアントが NFS サーバー上のファイルを共 ・ rpc. statd コンピュータの状態を監視するためのデーモン・プロ グラムで、 rpc. lockd や、ほかのコンピュータの rpc. statd と叫して重川します。 nfsd や rpc. lockd 、 rpc. statd は、起重圻は自動的に 処理をおこなってくれます。したがって、 NFS サーバー に対して管理者がおこなう設疋は mountd の動作、つま り NFS サーノヾーの、 ・どのディレクトリを ・どの NFS クライアントに対して ・どのようにマウントさせるか を決めることです。 /etc/exports 多くの UNIX では、これらの設定は /etc/exports というファイルに言当します 7 。基本的には、一ド記の情報 の組を 1 行すっ列挙します。 ・エクスポートするディレクトリ ・マウントを許可する NFS クライアント ・マウント広 ) オフション たとえは、 /usr/local と /home を工クスポートする 場合、 FreeBSD の /etc/exports ファイルは図 3 のよ うになります。 1 行目では、 NFS サーバーの /usr/local を、 mypc という NFS クライアントにェクスポートしています。 mypc からは読み書き可能であり、 mypc のスーパーユー サーは、共有したファイルを NFS サーバーのスーパー ューザーと同し権限で操作できます (-maproot オプシ ョン ) 。 2 行目は、ローカル・ネットワーク ( 192.168.1.0 ) 内 のすべての NFS クライアントに対して (-network オプ ション ) 、 /usr/local を言蒄呂し専用 (-ro オプション ) で 7 NFS サーバーが NFS クライアントに対してディレクトリを公開するこ とを、、、ェクスポートする " といいます。 39

4. UNIX MAGAZINE 2002年1月号

連載 UNIX Communication N0tes—O ために利用できるのが、 select() システムコールである。 select() は、複数のファイル識別子で指定される入力ソ ケットを監視し、カーネル内でプロックする。読み出せる ようになった ( 到着した ) ソケットがあるとプロックか外 れ、処理ルーチンを同一プログラム内でおこなうようにす るコードか書ける。これにより、複数のソケットを監視し ながら処理を夫行するルーチンか書けるようになった。 しかし、この実装には大きな問題がある。プログラムを 実行しているコンテキストは 1 つしかないので、リクエス ト処理ルーチンを実行しているあいだは、ほかのソケット に到着したデータや新たな接続要求はすべてカーネル内に イ尉寺される。けっきよく、 fork() は使わなくても、すべ ての処理がシリアライズされるため、高い性能か得にくく なった。もちろん、リクエスト処理ルーチンの処理量が大 きいと、処理待ちになるリクエストも増えることになって しまう。 そこで、登場するのがスレッドである。その考え方は 実装により多少異なるが、おおまかには次のようなもので ・スレッドを利用するプログラムでは、その実行時に複数 のスレッドを起動することができる。 ・ 1 つのスレッドは、実行を管理するためのコンテキスト をもつ。ここには、プログラム・カウンタとスタックだ けが用意されている。つまり、現在、どの部分を実行し ているかという情報と局所変数だけが各スレッドに割り 当てられている。 大域変数は、すべてのスレッドて共有される。したがっ て、或変数を使えばスレッド間での通信カそきる。 ・スレッドの生成や消去などは、プログラムで明カ勺に記 述できる。 スレッドを利用すると、ユーサー空間て稼動するプロ グラムで並列処理を簡単に記主できる。描丘の生能サー バーの世界では、スレッドの利用を目指す開発か続けられ ている。現在のスレッドの実装には、 BSD 系の pthread や Linux の linux pthread などがある。これらはそれ ぞれに実装形態か違い、長所もあれば短所もある。また、 BSD の pthread の実装のように、システムコールとの 親和がやや悪いという欠点は解消されつつあるが、完全 、解決されたわけではない。スレッドを利用するサーバー UNIX MAGAZIN E 2002 ユ はまだ少ないが、高性能サ→ヾーの世界ではスレッドを用 いた開発が一殳的になり始めている。 WWW サーバーの Apache 2.0 系列がその一例である。今後、高生能サー ーを構築する際には、使用されるプログラム自体がスレ ノ、 ッドを使う実装になると思われる。 ☆ 今回は、十分な処理性能が得られるサーバーの構築方 法について述べた。むろん、厳選された性能のよいパーツ を用いて高生能サーバーを構築するガ去もあるが、レイヤ 4 / 7 スイッチを使ったクラスタ化によって実現すること も増えてきている。とくに、商用 WWW サービスを提供 するサイトなどでは、常識といってもよいはどクラスタ化 サーバーの利用が進んでいる。 高生能サーバーを導入する場合は、レイヤ 4 / 7 スイツ チを用いたサーバー構成のノウハウを応用するとよい。最 近は、サーバー・プログラムそのものの高性能化もスレッ ドを用いた並列処理によって見されようとしている。ス レッドを用いた処理は SMP 型システムとの整合生もよ く、今後、高性能サーバー・プログラムの実装手法とし て普及する可能性がある。サーバーの実装を目指すソフト ウェア技術者は、スレッドを用いたプログラム開発の腕を 磨くべきであろう。 ( やまぐち・すぐる奈良先立斗 ! 物支彳大芋ギ完大学 ) [ 文献 ] [ 1 ] Lawrence S. Brakmo and Larry L. Peterson, "TCP Vegas: End t0 End Congestion Avoidance on a Global lnternet ” IEEE ノ 0 社ロ田 1 0 れ Selected Areas をれ Comm 社れを ca 0 れ , V01.13 , NO. 8 , Oct0ber 1995 (ftp: //ftp.cs.arizona.edu/xkernel/Papers/jsac.ps. Z) 65

5. UNIX MAGAZINE 2002年1月号

表 1 VMware 、 vorkstation 2.0 でのネットワーク送言 CPU の分布 ート 合言 カテゴリー VM M 日 VMNet 経由での送信 Lance ステータス・レジスタのエミュレ ホスト IRQ ( テパイス割込み ) の処理 Lance のエミュレート VMNet 経由での受信 VMM カテゴリー VMApp への切替えを要求する IN/OUT イ瓦想北を要求しない命令 イ瓦想北を要求する - ヨ殳命令 VMM て処理される IN/OUT Lance アドレスポートへの IN/OUT イ瓦想コードへ ( から ) の移行 IRET 命令のイ瓦想化 イ瓦想 IRQ ( テパイス割込み ) の伝土 俿冾 0.8 % 3.3 % 3.4 % 4.0 % 8.7 % 77.3 % 4.6 % 4.8 % 4.8 % 8.1 % 8.3 % 11.6 % 22.0 % 26.8 % 日の害冾 平均日繝 なし 3.93 s なし 0.74 卩 s 1.36 ″ s なし なし 7.45 ″ s 平均日鋿 1.8 s 5.2 s なし 3.1 / ↓ s 13.8 ″ s なし 最大のオーバーヘッドは、 VMApp , ) 鼬或切替えか要求される I/O 空間へ、のアク セスと、それを VMApp で処理する時間である。 くとも 2 倍は遅くなる引算である。 オーバーヘッドのおもな要因としては、このほかに表 1 中の複数のカテゴリーで必要な IRQ の処理か挙げられる。 AMD Lance の一反想 NIC は、 lntel EtherExpress の物 理 NIC と同様に、バケットの送受信のたびに IRQ ( テンヾ イス割込み ) を発行する。したがって、ネットワークの利 用率か高いワークロードではマシンの割込み率がきわめて 高くなる。ホスト協調型アーキテクチャでは、 VMM 領 域の実行中に受信される IRQ ごとに VMM の割込みハ ンドラか実行さホスト領域への切替えが発生する。ホ スト領域では、 IRQ に対応するホスト OS の割込みハン ドラを実行し、 VMApp に制御を渡してその結果の動作 が処理される。 IRQ がゲスト OS に関係するものである 場合 ( ゲスト宛のバケットが受信されたことを示すなど ) 、 VMApp はイ廨課 IRQ をゲスト OS に伝える必喫がある。 これには、 VMM 領域への切替え、イ瓦想マシンへの IRQ のイ幻土、ゲスト OS の割込みハンドラの実行がともなう。 VMM とホスト OS の割込みハンドラのはかにゲスト OS の割込みハンドラが実行されるため、 IRQ のコスト は増大する。また、イ反想割込み処理のルーチンは、イ廨当ヒ にコストがかかる牛罸雀モードの命令を実行する。表 1 を見 ると、 VMM が処理するはとんどの IN/OUT は仮想割 込みコントローラへのアクセスである。また、ほとんどの 166 IRET 命令はゲスト OS の割込みハンドラの最後で実行 される。そして、 VMM 領域でおこなわれる割込み処理 は、ホスト領域でおこなわれる割込み処理とくらべてはる かにコストか高い。これは、 VMM の割込みハンドラとホ スト領域への領域切替えか原因である。 ホスト協調型アーキテクチャには、この分析結果からは 分からないもう 1 つのオーバーヘッドがある。 VMApp と VMM は、イ廨課マシン用のイベントを生成するハ ウェア割込み ( ゲスト OS 宛のノヾケットが受信されるな ど ) と、仮想マシンとは関係のないハードウェア割込み を区別できないのである。これを区別できるのは、ホスト OS とそのドライバだけである。そこで、バランスをとる ための工夫をした。つまり、 VMApp は IRQ に応して、 VMM が VMApp に制御を戻したときに何もしないか、 あるいは VMApp から select() を呼び出す。 select() を 頻繁に呼び出しても無駄になるが、適度に呼び出さないと ネットワークの I/O イベントの処理リな遅れが生し る可能生がある。 3.3 ネットワークの仮想化による オーバーヘッドの軽減 領域切替えがオーバーヘッドの最大の要因だとした前節 の糸喆侖を踏まえ、ホスト協調型の I/O アーキテクチャを UNIX MAGAZINE 2002.1

6. UNIX MAGAZINE 2002年1月号

図 3 連載 /UNIX Communication Notes—O レイヤ 4 / 7 スイッチによる WYVW サーパーのクラスタ化 WWW要素サーバー レイヤ 4 / 7 スイッチ レイヤ 4 / 7 べし スイッチ レイヤ 4 / 7 スイッチ ハブ CGI-bin 要素サーバー ・ TCP コネクションの送信ホストアドレスと受信ホスト アドレスの組でフローを識別し、それにもとづいて要素 サーバーにフローを振り分ける。 ・サーバーの下丿獻態を定期的にチェックし、問題が発生 したサーバーを自重加勺にクラスタから切り離す。 ・ WWW アクセスの場合は、障害がしているサーバ ーに振り分けられた HTTP リクエストをほかのサー バーにリダイレクトする。 ・ Cookie を用いて、クラスタ内のどのサーバーを使うか を制御する。 ・ HTTP リクエストの内容を角斤し、 URL に応して使 用するサーバーを切り替える。 とくに、後半の 3 つの機能はアプリケーションに依存 するものであり、これらをまとめて、、レイヤ 7 スイッチ 機能 " と呼ふ合もある。これらの機能をうまく組み合わ せてクラスタを構成すオ L ばよい。 うまく構成するには、前回説明した、、処理の副作用 " を 十分に検詞するのがコツである。たとえば、 WWW サー バーであ川ま、 HTML ファイルなどの通常のファイルへ の単純な読出しアクセスの場合には副作用がないので、単 純なクラスタリングで対応できる。一方、 CGI プログラ ムの処理は副作用が多いので、レイヤ 7 スイッチ機能を 用いて別のサーバーに振り向けるしかない。これらの点を 考え合わせると、図 3 のような構成のシステムを作ること 60 HTML 文書管理用 バックエンド・システム UNIX MAGAZINE 2002.1 受け持っ処理の内容 ( この例ではデータベース ) によっ 能性か咼い。その場合も、バックエンド・サーバーが このバックエンド・サーバーがポトルネックになる可 ような形態にしている。このような構成にしたときは、 処理を完全にバックエンドのサーバー 1 台に集約する 処理の根にあることが分かる。そのため、副作用のある ば去絲冬的にデータベース・サーバーが副作用をともなう る処理といっても、その内容をよくみていくと、たとえ とするものを専用のクラスタへ振り向ける。副作用のあ は HTTP リクエストのなかで副作用のある処理を必喫 ・同しく 2 段目のレイヤ 4 / 7 スイッチのうち、下の C ディスクに一尉寺する。 HTML ファイルなどの読出しのみのデータをローカル サーバーに平均化して振り向ける。各要素サーバーは、 としての機能をもち、 HTTP リクエストを複数の要素 ・ 2 段目のレイヤ 4 / 7 スイッチのうち、上の B は SLB セスをうける。 HTTP アクセスと、副作用をともなう CGI-bin アク チ A のレイヤ 7 スイッチ機能により、副作用のない ・インターネット側仏 }) に設置したレイヤ 4 / 7 スイツ なアイデアにもとづいて構築されている。 単に復習しておこう。この WWW システムは、次のよう この構成については 2001 年 11 月号で紹介したが、簡 になるだろう。 バックエンド・システム テータベース用

7. UNIX MAGAZINE 2002年1月号

連載 /UNIX Communication Notes—O って、トランスポート層とアプリケーション層でのプロト コルに起因する遅延は、プロトコルそのものを変えないか ぎり去宿できない。ただし、・カーネル内に実装されたプロ トコル処理自体は、サーバーやクライアントの匪能に左右 される。 プロトコルの構造に起因する遅延の典型は、 TCP のウ インドウフロー制御によって発生するものだろう。 TCP のパラメータ設定によって去噌できる可能性はあるが、根 本的に解決するには、 TCP においてウインドウフロー 制御の代わりにより性能の高い制御方式を導入するしかな い。たとえは、 TCP Vegas[I] と呼はれる制御方式は、レ ート制御 (rate control) の概念を採り入れ、広帯域ネッ トワークにおける TCP の能を改善しようという試みで ある。この分野の研究は現在も活発に進められており、と くに、山も匠のネットワークの広或化に対応するさまざま な方式が考案されている。 アプリケーション層での遅延を矢可宿するには、アプリ ケーションごとに対応するしかない。 HTTP であれは、 HTTP 1.1 てラ尊入された persistent connection や、デ ータ転却芋の gzip 日引彡式の選択などが代表的な手法で ある。これらの改善手法は、アプリケーション・プロトコ ルごとに検言寸されている。 一方、プロトコル処理そのものの遅延は、カーネルにお けるプロトコルの実装やシステムの性能に左右される。た とえは、 80486 DX2 66MHz を用いた PC UNIX サー ーは、現在のシステムと上交して明らかにプロトコル処 理か遅くなる。このような場合は、高速な CPU を使っ て処理速度を高めれは、カーネル内でのプロトコル処理に ともなう遅延をまできる。しかし、山も匠のシステムでは CPU がポトルネックになっていることは少ないので、シ ステムの単純なアップグレードによって性能か劇的に改善 されるわけではない。これは、サーバーでの処理によって ける遅延にも当てはまる。 サーパーて、の里による過匡 サーバーでの処理による遅延をいかに矢聾宿するかは、サ ーバーの友を考えるうえでもっとも重要な譏題である。 サーバーにおける処理の性能改善を考えるうえで重要な のは、何がポトルネックとなっているかを把握すること を一一 ~ これさえ分かれば、その要素を高性能なものに交 UNIX MAGAZINE 2002.1 換することでシステム性能の改善か図れる。 1 つのポトル ネックを改善しても、今度は別の要素がポトルネックにな ることもある。このようなときは、ポトルネックを毆亦し ながら性能を改善する作業が必要になる。単一のサーバー では、次のような要素がポトルネックになりうる。 最初に考えなけれはならないのは、ハードディスクと ファイルシステムである。とくにハードディスクは要注意 である。ハードディスクの性能は、ハードディスク自体 とその上に実装されるファイルシステムの 2 つに分けて 考える必要がある。前者については、たとえはディスク回 転数の遅いドライプはディスクアクセスか遅く、性能力咄 ない。とくに、ディスク I/O カ噸発する処理ではその傾 向か顕著になる。実際、ラップトップ PC の内蔵ディス クは、デスクトップ PC のそれと上交して回転数が遅い のか通である。これを回転数の高いものに交換するだけ で、性能か劇的に改善される場合がある。サーバーのよう な大規模なシステムであれば、前回説明した RAID 技術 の導入により、アクセス性能の改善を図る場合が多い。 一方、ファイルシステムについては、その構造によって 処理のオーバーヘッドが変わるので、それぞれに性能が大 きく異なる。たとえは、同し BSD FFS (Fast File Sys- tem) であっても、カーネル内の実装は OS ごとにかなり 違う。そのため、 FreeBSD と NetBSD を上交した場合、 前者の他のほうか圧倒的に性能がよい。また、異なるファ イルシステムである FreeBSD の ffs と Linux の ext2fs では、一殳に後者のほうか高速である。このように、ファ イルシステムの実装の違いによって性能が大きく変わるこ ともある。このため、高性能サーバーを設計する場合は、 とくにアプリケーションの特生や、使用する OS 上て利 用可能なファイルシステムの機能を勘案し、どれを使うか を寸分に考える必喫がある。さらに、ファイルシステムに は性能を左右するパラメータがあり、たいていはカーネル のコンパイル時のオプションでチューニングできる。この 点についても、十分に検討すべきであろう。 処珊生能を決める大きな要因の 1 つに CPU がある。最 近の CPU はかなり高性能なうえに、続々と高速な CPU が発表されている。このため、数 - I ・年前のシステムならと もかく、山も丘は CPU がポトルネックになることはあまり ない。事実、クロックの高い CPU に交換しても、まっ たく性能が改善されない場合も少なくない。ただし、スト 57

8. UNIX MAGAZINE 2002年1月号

旧 v6 ヘッダ 始点アドレス 終点アドレス 旧 v6 ヘッダ 始点アドレス 終点アドレス 旧 v6 ヘッダ 始点アドレス 終点アドレス 旧 v6 ヘッダ 始点アドレス 終点アドレス = 旧 旧 v6 ヘッダ 始点アドレス 終点アドレス ノード S ノードに ノード旧 ノード D 図 12 終点オプションヘッタ 終点オプションヘッダ番号 : 60 = に 連載 / 旧 v6 の実装ー 0 図 11 IPv6 ヘッダの終点アドレスの変化 = S = D = S = S = S = S = D 経路制御ヘッダ Segments Left = 3 Add ress[ 1 ] = Address[2] = に Address[3] = 13 経路制御ヘッダ Segments Left = 3 Address[1] = Address[2] = 13 Address[3] = D 経路制御ヘッダ Segments Left = 2 Address[1] = Address[2] = 旧 Address[3] = D 経路制御ヘッダ Segments Left = 1 Add ress[ 1 ] = Address[2] = に Address[3] = D 経路制御ヘッダ Segments Left = 0 Address[1] = Add ress[2] = に Add ress[3] = 旧 / ヾケット初期状態 ノード S : 終点アドレスを経路制御ヘッダの末尾に追加し、最初の 中継ノードを終点アドレスに設定して送信・・・・① ノー日 1 : 次の中継ノードのアドレスと現在の終点アドレスの値を 入れ替え、 Segments Le 代を 1 減じて送信・・・② ノード 12 : 以下同様 Segments Le 負が 0 なので、自分宛の / ヾケットとして処理・ 3 Next Header 旧 d 「 Ext Len Options (variable) バケットは、 IPv6 ネットワークの糸各情報に従って ll へ酉占されます。 II は、バケットの終点アドレスとして 自分自身カ甘旨定されているのでバケットの処理を始めます が、拡リ、ツダを処理している途中で、糸翻雅卩ヘッダが 存在することを発見します。経路制笹いッダを処理した結 果、 II は自分が最終的な宛先ではないことを認識します。 そこで、 ll は次の中継ノード 12 と点での終点アドレ ス II を入れ替え、 Segments Left の値を減らしたあと、 再度 IPv6 ネットワークへバケットを送信します ( 図 11 ー 2 ) 。以後同様に 12 、 13 でバケットか処理さ最終的 にノード D に到達します。ノード D は Segments Left が 0 であることから自分か最終宛先であると認識し、通常 72 のバケット処理をおこないます ( 図 11 ー 3 ) 。 終点オプションヘッダ UNIX MAGAZINE 2002.1 ダは、糸各制御ヘッダに指定された各中継ノードと最糸勺 ります。経各制御ヘッダよりも前の終点オプションヘッ ヘッダの前、暗号化へッダの後ろ ) に出現する可能性があ プションヘッダは IPv6 バケット中で 2 カ所 ( 糸各制御 刻、ツダの推奨国のところで説明したように、終点オ tions の形式も中点オプションヘッダの場合と同様です。 形式的には中継点オプションヘッダと同しです。 Op- プションかオ褓内されます ( 図 12 ) 。 ケットの終点アドレスに指定されたノードて処理されるオ 終点オプションヘッダは才比、ツダの 1 つで、 IPv6 パ

9. UNIX MAGAZINE 2002年1月号

プログラミング・テクニック しかし、接続するのが echo サーバーではない、つま り複数の入力行を読み込んでから数行ぶんの応答をまとめ て返すサーバーの場合、このプログラムでは対応すること ができません。どの程度の入力をサーバーに送れは応答が 返ってくるかカ吩からないため、標準入力からの入力を読 み込みつつ、それをサ→ヾーに送る必要があります。さら に、サーバーからの返答を監視しなければなりません。そ のためにおこなうのか非期の入出力てす。 ・ファイル言当子の複製 ・ close-on-exec フラグの取彳等と疋 ・ステータスフラグの取得と設定 ・入出力関連シグナルの受信プロセスの取得と設定 ・レコードロックの取得と解除 があります。非プロッキング入出力は、ステータスフラグ て蒲衂されています。実際の処理は次のようになります。 fcntl(fd, F—GETFL, 0 ) ) perror("fcntl") ; exit(l); if (fcntl (fd, F—SETFL , f ー O—NONBLOCK) perror("fcntl") ; exit(l); if ( (f = 非プロッキング入出力 ます、実際に入出力をおこなっている process 関数が 呼び出される状況と、この関数の重川乍について石忍してお きましよう。 ます、 fcntl に対して F-GETFL コマンドを実行し、 この関数か呼び出されるときには、 TCP を利用してい ファイル・ディスクリプタの現在のステータスフラグを取 る場合はすでに接続か確立した TCP のソケットが引数 得します。続いて、 F-SETFL コマンドによりステータ として渡されます。 UDP の場合には、接続という念は スフラグを設定します。このとき引数として、最初に取得 ありませんが、バケットの送出先があらかじノ旨定された したフラグの値と非プロッキング入出力を示す O-NON- 状態て呼び出されます。つまり、いすれも read や write BLOCK とのビットごとの論理和をとった値を指定しま などのシステムコールを使ってデータを読み書きできるよ す。この処理により、もとのステータスフラグから非プロ うになっています。ただし、相手側とのやりとりのなか ッキング入出力のフラグのみを変更したものを設定するこ で、ネットワークからの入力と標準入力の両方を順番に読 とかできます。値を取得迂すに O-NONBLOCK だけを み書きしていては正しく重川乍しなくなってしまいます。そ 引数として F-SETFL を実行すると、ほかのフラグか設 こで、ネットワークからの入力でも標準入力でも、言も囚み 定されていた場合にこれらがクリアされてしまいます。上 か可能になった段階で読み込んで対応する出力先に出力し 己の処理は、このような問題を避けるための工夫です。 ようとします。 上に示したコードでは fd を非プロッキング入出力に設 言ムみが可能かどうかを調べるのは、ネットワークや標 定しました。次に、標準入力についても非プロッキング入 準入力から読み込むべきデータがない場合にプロセスカワ・ 出力の設定をしたあと、サンプル・プログラムのような入 ロック ( 入力待ちで停止 ) してしまうからです。逆にいえ 出力に関するループを実行すればよいのですが、ループの ば、プロックさえしなければいつ読み込んでもかまわない 内部をすこし変更する必要があります。非プロッキング入 はすです。そのためには、 fcntl システムコールを使って、 出力をおこなうファイル・ディスクリプタは、読み出す ファイル・ディスクリプタか非プロッキング入出力をお データがないか書き込む準備ができていない場合にエラー こなうように設定します。 を返し、 errno を EAGAIN に設定するためです。これ fcntl システムコールは次のような形式でイ吏います。 は実際にエラーが発生したわけではなく、一日勺に実行で fcntl ()d , command, arg) きないことを表すのですから、エラーを無視しなけれはな りません。そのためのコードは次のようになります。 fd には処理の対象となるファイル・ディスクリプタを、 command にはおこないたい処理を表すマクロを指定しま for ( ; / * 端末から入力 * / す。さらに処理に対する引数を arg に指定します。 if ((len = read(), buf , BUFSIZ)) く 0 ) { if (errno ! = EAGAIN) { fcntl で可能な処理としては、 perror("read") ; 1 三ロ 77 UNIX MAGAZINE 2002.1

10. UNIX MAGAZINE 2002年1月号

連載 / lPv6 の実装ー 0 図 4 中点オプションヘッダ オプションヘッダ番号 : 0 Next Header Hdr Ext Len Options (variable) 1. 中点オプションヘッダ 2. 終点オプションヘッダ 1 3. 糸各制御ヘッダ 4. 断片ヘッダ 6. 暗号化へッダ 7. 終点オプションヘッダ 2 注目すべき点は、終点オプションヘッダが 2 回登場し ていることです。最初の終点オプションヘッダは、経路 缶雅卩ヘッダよりも前に配置されます。この位置の終点オプ ションヘッダは、 IPv6 ヘッダて指定された最終的な終点 ノードに加え、糸各制徊ヘッダて指定された各中継ノード でも処理されます。 2 つ目の終点オプションヘッダは、暗 号化へッダより後ろに配置されます。この位置にある終点 オプションヘッダは、終点ノードにおいてのみ処理されま す。さらに、必要であれ ( 部号化へッダを用いて隠蔽する こともできます。 中系点オプションヘッダには、 IPv6 バケットを転送す る中継ノード ( ルータ ) で処理されるオプションかオ褓内さ れます。このヘッダの形式を図 4 に示します。 Next Header には、次に続く刻に、ツダ番号か上イ立層 プロトコル番号が入ります。 Hdr Ext Len には、中点 オプションヘッダ本のオクテット数を 8 て割った値か ら 1 を引いたものかオ絲タされます。たとえば、 Hdr Ext Len の値が 0 の場合には中点オプションヘッダの全長 は 8 オクテット、 1 であ川ま 16 オクテットとなります。 中継点オプション、終点オプションの書式 中点オプションヘッダと終点オプションヘッダには、 一一一一一一一一さまざまなオプシーヨンかオ絲タされます。これらのオプショ 中継点オプションヘッタ UNIX MAGAZINE 2002.1 ンは、オプション型、オプションの長さ、オフションの 値のいわゆる TLV (Type 、 Length 、 Value) 形式で指 定します。オフションの形式を図 5 に示します。 Option Type はオプションの不鶤頁を示す値で、各オプ ションごとに固有の値をもっています。 Opt Data Len では、 Option Data の長さ ( 単位はオクテット ) を指定 します。 Opt Data Len には、 Option Type と Opt Data Len 自身の長さは含まれないので注意が必要です。 Option Type の上位 3 ピットには特別な意味があり ます。ます、先頭 2 ピットで、不明なオプションの処理 ガ去を決定します。 IPv6 ノードは、オプションの処理中 に未知のオプション型を発見した場合、以下の規則に従っ て処理を進めます。 00 : このオプションを無見し、以後の処理を続ける。 01 : バケットを破棄する。 10 : このオプションを含む IPv6 バケットの始点アドレ スに対して、不明なオプションを示す ICMP ェラーを する。 11 : このオプションを含む IPv6?S ケットの終点アドレ スがマルチキャスト・アドレスでない場合に限り、始 占アドレスに向けて不明なオプションを示す ICMP ェ ラーを返送する。 3 ビット目では、オプションの値カ云送中に変更される かどうかを指定します。 0 : オプションの値は転送中に変更されない。 1 : オプションの値は転送中に変更される場合がある。 バケットの改竄を防ぐために認証ヘッダなどを用いてい る場合、転送中 : ンヾケットのオプション部分か変更される と、終点ノードがバケットを石忍したときにエラーになっ てしまいます。したがって、変更される可能生のあるオ フションについては、事前に指定しておかなければなりま せん。 69