メッセージ - みる会図書館


検索対象: UNIX MAGAZINE 2005年12月号
22件見つかりました。

1. UNIX MAGAZINE 2005年12月号

722 723 724 725 連載 / 旧 v6 の実装ー 0 return ( 0 ) ; mono—time . tv—sec) { if (sc->hif-mps-lastsent + 1 > / * rate limitation . * / 744 745 746 747 748 749 750 m—free(m) ; m = NULL ; if (m = = NULL) return (ENOBUFS) ; m—>m—pkthdr. rcvif = NULL ; 723 ~ 725 行目でメッセージの送信頻度を調整します。 hif-mps-lastsent には、 sc で指定されるホーム・ネット ワークに向けて、最後にモバイル・プレフィックス要求メ ッセージを送信した時刻カ第己録されています。もし、最後 にメッセージを送信してから 1 秒以内にメッセージを再送 信しようとしたら、ネットワークへの負荷を減らすために 送信を控えます。仕様では初期再送時間は 3 秒で、指数的 に再送時間を増やしながら、対応する応答メッセージを受 信するまで再送しなければなりませんが、その部分は実装 されていません。 727 728 729 730 731 736 737 732 / * estimate the size Of message . * / sizeof (*ip6) + sizeof (*mp—sol) ; maxlen / * XXX we must determine the link type 0f our home address instead using hardcoded ) 6 ) * / maxlen + = (sizeof (struct nd—opt—hdr) + 6 if (max—linkhdr + maxlen > = MCLBYTES) { return (EINVAL) ; 728 ~ 737 行目でメッセージをオ村する mbuf の大きさ を計算します。メッセージの長さは、 IP ヘッダ (ip6 変 数 ) とモバイル・プレフィックス要求メッセージ (mp-sol 変数 ) のサイズから計算できますが、出力過程の最終段階 でデータリンク層へッダが付加されることをあらかじめ考 慮して、 732 行目で max 」 inkhdr ぶんを加えておきます。 こうすることで、データリンク層へッダを付加するときに よぶんなメモリ確保処理を抑制できます。メッセージ長が mbuf の最大サイズ (MCLBYTES) に収まらない場合は、 ェラー終了します。 なお、 731 行目で近隣探索オプションの長さを加えてい ますが、 729 ~ 731 行目は前後のコードをほかの処理部分 からコピーしたときの名残りで、モバイル・プレフィック ス要求メッセージの送イ言処理としては不要です。 739 740 741 742 743 / * get packet header. * / MGETHDR(m , M_DONTWAIT , MT-HEADER) ; if (m & & max—linkhdr + maxlen > = MHLEN) { MCLGET (m , M_DONTWAIT) ; if ( (m->m—flags & M—EXT) UNIX MAGAZ 工 NE 2005. 12 740 ~ 747 行目で mbuf を確保します。必要なサイズの mbuf か確保できなかった場合、 749 行目でエラー終了し ます。 rcvif はバケット受信時の入力インターフェイス情 報ですから、出力時は NULL で初期化しておきます ( 750 行目 ) 。 icmp61en = sizeof (*mp—sol) ; 752 753 m—>m—pkthdr. Ien = m—>m—len 754 m—>m—data 十 = max—linkhdr ; 753 行目で mbuf のバケットサイズをモバイル・プレ フィックス要求メッセージの大きさに設疋し、 754 行目で mbuf の先頭に rnax 」 inkhdr ぶんの余裕ができるように バケットを橋内するためのポインタを調整します。 sc—>hif—mps—id = mip6—mps—id + + ; 移動ノードは、送信したモバイル・プレフィックス要求 メッセージと、返送されたモバイル・プレフィックス応答 メッセージを対応づけるため、メッセージ中に識別番号を 定します。この番号はホーム・ネットワーク構造体 (hif- softc 構造体の hif-mps-id) に f 尉芋されており、メッセー ジを送信するたびに 1 ずっ増やされます。 図 2 の 760 ~ 773 行目でメッセージの各フィールドを 設疋します。モバイル・プレフィックス要求メッセージは ICMPv6 メッセージの一種です。形式的には ICMPv6 の基本へッダと同一になります。 ICMPv6 のタイプ番号 は MIP6-PREFIX-SOLICIT ( 146 ) 、コード番号は 0 を設疋します。 mip6-ps-id には、要求メッセージと応答 メッセージを対応づけるための識別番号が定されます。 図 3 の 776 行目で IPv6 バケットのペイロード長を設 定し、 777 ~ 778 行目で ICMPv6 メッセージのチェッ クサムを計算します。作成されたバケットは 781 行目の ip6-output() でホーム・エージェントに向けて送信され ます。なお、メッセージの始点アドレスがホームアドレス になっているため、実際にはネットワークに送出される前 に、終オプションヘッダとホームアドレス・オプション カ咐加され、気付アドレスから送信されることになります。 sizeof(*ip6) + icmp61en; 756 95

2. UNIX MAGAZINE 2005年12月号

連載 / Ⅲ v6 の実装ー 0 図 4 メッセージの始点アドレスと終点アドレスび忍 869 870 871 872 873 874 875 883 884 885 mbu = mip6—bu—Iist—find—home—registration(&hif—>hif_bu_Iist , if if &ip6—>ip6-dst) ; (mbu = NULL) { error = EINVAL; goto freeit ; ( ! IN6_ARE_ADDR_EQUAL (&mbu—>mbu_paddr , &ip6->ip6_src) ) { error = EINVAL ; goto freeit ; ( (caddr—t) ip6 + off) ; 833 行目で、 ip6 変数に IPv6 バケットの先頭アドレ スを設定します。そして、 835 行目の IP6-EXTHDR- CHECK() でメッセージ全体が連続メモリ領域に配置さ れているかどうかを確認します。連続メモリ領域に格納さ れていない場合、メッセージの内部情報にポインタ経由で アクセスできなくなります。 IP6-EXTHDR-CHECK() のなかで検証に失敗したら、 EINVAL 工ラーが返されて 関数を終了します。 848 849 850 851 852 853 / * find mip6—ha instance . * / mha = mip6—ha—1ist—f ind—withaddr ( &mip6-ha—1ist , &ip6—>ip6-src) ; if (mha = = NULL) { error = EINVAL ; goto freeit ; 860 } 856 行目の hif-list-find-withhaddr() は、引数として 渡されたホームアドレスに関連するホームネットワーク・ インターフェイスへのポインタを返します。移動ノードが 送信した要求メッセージの始点アドレスは、移動ノードの ホームアドレスに設疋されていました。よって、対応する 応答メッセージの終点アドレスは、そのホームアドレスで あるはずです。もし、応答メッセージの終点アドレスに指 定されているホームアドレスに対応するホームネットワー ク・インターフェイスがなければ、そのホームアドレスは 不正なアドレスとみなせます。 862 / * sanity check. * / if (hif—>hif_location ! = 863 864 865 866 HIF_LOCATION_FOREIGN) { / * MPA is processed 0 Ⅱ ly we are foreign. * / error = EINVAL; goto freeit ; 849 行目の mip6-ha 」 ist-find-withaddr() は、引数と して指定されたアドレスが、移動ノードが知っているホー ム・エージェントのものかどうかを調べ、そうであればホ ーム・エージェント情報を十帑内している構造体 (mip6-ha 構造体 ) へのポインタを返します。移動ノードは、そもそ も自分が登録しているホーム・エージェントにモバイル・ プレフィックス要求メッセージを送信したのですから、そ の応答として返送されてくるモバイル・プレフィックス応 答メッセージの始点アドレスは、移動ノードのホーム・エ ージェントのアドレスになるはすです。対応するホーム・ 工ージェント情報がみつからなければ、受信したバケット は不正なバケットとみなせます。 855 856 857 858 859 / * find relevant hif interface . * / hif = hif_list-find-withhaddr( &ip6->ip6-dst) ; if (hif = = NULL) { error = EINVAL ; goto freeit ; UNIX MAGAZINE 2005. 12 867 } 863 ~ 867 行目は、出先ネットワーク以外でモバイル・ プレフィックス応答メッセージを受信したときの処理です。 出先ネットワーク以外 ( すなわち、ホーム・ネットワーク ) での応答メッセージの受信はエラーとして処理されます。 869 ~ 885 行目 ( 図 4 ) は、受信したモバイル・プレフ イックス応答メッセージの始点アドレスと終点アドレスの 組が正しいかどうかを調べています。モバイル・プレフ イックス要求メッセージは、移動ノードが登録しているホ ーム・エージェント宛に送られます。その応答となるメッ セージも、登録先のホーム・エージェントから返送されて こなければなりません。 869 行目の mip6-bu-list-find- home-registration() で、応答メッセージの終点アドレス ( 移動ノードのホームアドレス ) に対応する対応付け更新エ ントリを検索します。さらに、検索されたエントリに設定 97

3. UNIX MAGAZINE 2005年12月号

連載 / 旧 v6 の実装ー 0 図 2 メッセージの各フィールドの言又疋 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 / * fill the mobile prefix solicitation ・ ip6 = mtod(), struct ip6-hdr * ) ; ip6->ip6—f10w = 0 ; ip6->ip6—vfc & = -IPV6_VERSION_MASK ; ip6—>ip6—vfc ー = IPV6-VERSION; / * ip6—>ip6—p1en will be set later * / IPPROTO_ICMPV6 ; ip6—>ip6-nxt ip6—defh1im ; ip6—>ip6-h1im ip6->ip6-src *haddr ; ip6->ip6-dst *haaddr ; mp—s01—>mip6—ps—reserved = 0 ; mp—s01—>mip6—ps—id = htons(sc—>hif—mps—id) ; mp—s01—>mip6—ps—code mp—s01—>mip6—ps—type = MlP6—PREFlX—SOLlClT; mp—sol (struct mip6-prefix-s01icit * ) (ip6 + 1 ) ; 図 3 IPv6 バケットの送信 775 776 777 778 779 780 781 785 786 790 791 792 793 794 795 796 } / * calculate checksum. * / ip6—>ip6—p1en = htons( (u—int16-t) icmp61en) ; mp—s01—>mip6—ps—cksum = 0 ; in6-cksum(), IPPROTO—ICMPV6, mp—s01—>mip6—ps—cksum icmp61en) ; ip6—output (), 0 , 0 , 0 , 0 ,NULL error if (error) { / * update rate limitation factor. * / sc—>hif—mps—lastsent = mono—time . tv—sec ; return (error) ; sizeof (*ip6) , 793 行目でメッセージの送信時刻を記録し、関数を終了 します。 モバイル・プレフィックス応答の受信 モバイル・プレフィックス要求メッセージを受信した ホーム・エージェントは、その応答としてモバイル・プ レフィックス応答メッセージを返送します。メッセージは ICMPv6 の一種ですから、 ip6-input() 、 icmp6-input() を経由して mip6-icmp6-mp-adv-input() にたどり着き mip6-icmp6-mp-adv-input() はモノヾイル・プレフィ ックス応答メッセージの処理関数で、 3 つの引数をもちま す。 m は入力されたメッセージを十内した rnbuf へのポ インタ、 0 仕は IPv6 ヘッダからモバイル・プレフィック ス応答メッセージの先頭までのオフセット、 icmp61en は モバイル・プレフィックス応答メッセージの長さです。 830 / * XXX IPSec check . * / モバイルプレフィックス・メッセージは IPsec で保護さ れなければなりません。本来なら、この時点でバケットが 保護されていたかどうかを確認すべきですが、未実装とな っています。 ます。 798 799 800 801 802 8 ( ) 3 96 static int mip6—icmp6—mp-adv—input (m , struct mbuf *m; int off ; int icmp61en; off, icmp61en) 833 835 836 ip6 = mtod(), struct ip6—hdr * ) ; IP6_EXTHDR_CHECK (m , off , icmp61en , EINVAL) ; (struct mip6—prefix—advert * ) mp— adv UNIX MAGAZ 工 NE 2005. 12

4. UNIX MAGAZINE 2005年12月号

連載 / Ⅲ v6 の実装ー 0 図 5 タイプ 2 糸篩断卸ヘッタ付きのバケットかどうかび砡忍 887 888 889 890 891 892 893 894 895 896 897 898 899 900 / * check type2 routing header. * / mtag = ip6-findaux(m) ; = NULL) { if (mtag / * this packet doesn't have a type 2 RTHDR. error = EINVAL ; goto freeit ; } else { ip6a (struct ip6aux * ) (mtag + 1 ) ; goto freeit ; error = EINVAL; / * this packet doesn't have a type 2 RTHDR. * / if ( (ip6a—>ip6a—f1ags & IP6A-ROUTEOPTIMIZED) 図 6 言リ番号似忍 903 / * check id. if it doesn't match, send mps . * / 904 if (hif—>hif_mps—id ! = ntOhs (mp—adv—>mip6—pa—id) ) { 9 ( ) 5 906 907 mip6—icmp6—mp—s01—output (&mbu->mbu-haddr , &mbu—>mbu-paddr) ; goto freeit ; error = EINVAL ; 908 } されているホームエージェント・アドレスが、受信した応 答メッセージの始点アドレスと等しいかどうかを確認しま す ( 875 行目 ) 。 モバイルプレフィックス・メッセージは、移動ノード のホームアドレスを使ってやりとりされます。すなわち、 受信の際にはタイプ 2 経路制御ヘッダが指定されていな ければなりません。図 5 の 888 ~ 900 行目では、受信し たバケットにタイプ 2 経路制御ヘッダが付いているかど うかを確認します。タイプ 2 経路制御ヘッダがあれば、 バケットの付随情報を格納する構造体 (ip6aux 構造体 ) に IP6A-ROUTEOPTIMIZED フラグが設定されま す。このフラグが設疋されていなければ、不正なバケット として破棄します。 図 6 の 904 ~ 908 行目は識別番号の確認です。受信し た応答メッセージに含まれている識別番号 (mip6-pa-id) が、移動ノードが要求メッセージに含めていた識別番号と 異なっていたら、メッセージを破棄します。 なお、ホーム・エージェントは移動ノードからの要求が なくても、必要に応じてモバイル・プレフィックス応答メ ッセージを送信することがあります ( ただし、 KAME で は実装されていません ) 。この場合、識別番号が一致するこ とはありません。移動ノードは、識別番号が一 -- - 教しないメ ッセージを受信すると、最新のプレフィックス情報を取得 するために要求メッセージを送信します ( 905 行目 ) 。 98 910 911 912 916 917 918 919 sizeof (*mp—adv) ; icmp61en nd6—option—init (mp—adv + 1 , icmp61en, &ndopts) ; if (nd6-options (&ndopts) く 0 ) { / * nd6—options have incremented stats * / error = EINVAL; goto freeit ; 910 ~ 919 行目は近隣探索オプションの解析処理です。 モバイル・プレフィックス応答メッセージには、近隣応 答メッセージで利用されるプレフィックス情報が、近隣 応答メッセージと同じ形式で格納されています。 nd6-op- tion-init ( ) で解析結果をオ内する領域を初期化し、 nd6- options() でオプション情報を取り出します。以後、オプ ションの内容は ndopts 変数経由で参照できます。 921 行目のループで、メッセージに含まれている近隣探 索オプションを処理します ( 図 7 ) 。モバイル・プレフィッ クスの処理では、プレフィックス情報以外は不要なため、ほ かのオプションを無視します ( 925 ~ 926 行目 ) 。 930 ~ 964 行目はプレフィックス情報オプションの正 当性の確認です。オプション長が 4 であること ( 930 行 目 ) 、プレフィックス長が 128 以下であること ( 937 行 目 ) 、指定されたプレフィックスがマルチキャストやリンク ローカルでないこと ( 945 ~ 946 行目 ) 、また、 RFC2374 ( RFC3587 で改訂 ) で規定されているユニキャスト・アド UNIX MAGAZINE 2005 . 12

5. UNIX MAGAZINE 2005年12月号

図 12 STREAMS 図 13 STREAMS のスタック ユーザー空間 カーネル空間 ユーザー空間 カーネル空間 stream head STREAMS ドライバ ムおよび STREAMS ドライバは、、 stream" と呼ばれ る双方向の通信チャネルで結ばれる。一般に、ユーザ ・プログラム側を、、上流 " 、ドライバ側を、、下流 " と呼 ぶ。ユーザー・プログラムとじかに接している部分 ( カ ーネル空間とユーザー空間の境目 ) が最上流で、ここが stream head" である。また、 stream の最下流には STREAMS ドライバがある ( 図 12 ) 。 おもしろいのは、 stream head とドライバのあいだに 、、 STREAMS モジュール " を押し込めることだ。たと えば、シリアルポートのさきに端末カ甘妾続されている場 合には、 ldterm (7M) と ttcompat ( 7 ) という 2 つ のモジュールが入っている。さらに、ホストマシンの日 本語文字コードが EUC で端末側が Shift-JIS であれ ば、文字コード変換モジュール jconvs (7M) を入れる ことで日本語が正しく扱えるようになる ( 図 13 ) 。ネッ トワークプロトコル・スタックも同じように実装できる。 ドライバの上に ip(7P) モジュールを入れれば、 IP で の通信が可能になる。 このように、変換などのロジックは各モジュール内に隠 蔽される。そして、、、プロトコル・スタック " を構築する には、必要なモジュールを文字どおりスタック (stack : 積み重ねる ) するだけでよい。 また、 STREAMS には、、多重化ドライバ " というもの がある。これは通信チャネルの多重化を実現する仮想ド ライバで、上位、下位ともに複数の stream を接続し、 メッセージ奐をおこなうことができる ( 図 14 ) 。これ を利用すれば、ファイアウォールのフィルタ・モジュー ルなどが実装できる。 可変長メッセージを使ったデータ交換 データは、メッセージ・プロックに格納されてモジュー ル間を往き来する。つまり、たんなるバイトストリーム とは違って、データに論理的な区切りを含めることがで 90 stream head ttcompat(7M) Idterm(7M) jconvs(7M) tty ドライバ STREAMS モジュー丿レ STREAMS ドライバ きる。メッセージのデータ長は可変で、各モジュールで 変換などの謝奐えが可能である。プロトコル・モジュー ルであれば、ヘッダとチェックサム・コードの追加と除 去をするだろうし、暗号化モジュールならデータの暗号 化と復号ができる。 ・フロー制御機能をもつメッセージキュー 各モジュールには、 stream ごとにメッセージを受け付 ける入口が 2 つある ( 下流向けと上流向け ) が、 メッセージキューがある。このキューの状態はほかのモ ジュールから確認できるので、事実ー E 、モジュール間で フロー制御が可能になる。また、内部制御メッセージな どはフロー制御の対象から外すこともできる。 STREAMS フレームワークにおいて、ネットワーク・ デバイスドライノヾは STREAMS ドライバに位置づけられ る。また、 STREAMS ドライバはデバイスノードを作成 するが、 こからデータを生のままやりとりするのではな く、、、 DLPI (Data Link Provider Interface)"4 という インターフェイスを使う。 DLPI は、通信サービスを提供 する側 (Ethernet ドライバなど ) と、そのサービスを利用 する側 ( ユーザー・プログラムや ip モジュールなど ) との あいだのプロトコルであり、さまざまな通信形態を考慮し たものである。だが、すべての通信形態について説明する 4 http://www.opengroup ・ org/pubs/catalog/c811. htm UNIX MAGAZINE 2005 . 12

6. UNIX MAGAZINE 2005年12月号

連載 / 旧 v6 の実装ー 0 図 1 モバイル・プレフィックス要求メッセージの送信 222 223 224 225 226 227 228 229 230 231 232 233 234 235 } for (hif = LIST—FIRST(&hif_softc_1ist) ; hif ; hif = LIST_NEXT(hif , hif_entry) ) { if ( ! IN6_IS_ADDR_UNSPECIFIED(&mpfx—>mpfx—haddr) ) { mbu = mip6—bu—1ist—find—home—registration( &hif->hif-bu-list , &mpfx—>mpfx-haddr) ; if (mbu ! = NULL) { error = mip6—icmp6-mp-s01-output ( &mbu->mbu-haddr , &mbu->mbu-paddr) ; return (error) ; break ; レフィックス情報には有効時間が設定されており、有効時 間が切れた情報は破棄されます。 移動ノードのホームアドレスは、ホーム・プレフィック スから生成されます。 KAME の実装では、近隣探索のア ドレス自動設定と同等の仕組みを用いて、ホーム・プレフィ ックスからホームアドレスが自動生成されます。 MobiIe IPv6 では、ノードを識別する不変の識別子としてホーム アドレスを利用します。移動ノードは、ホーム・プレフィ ックスの有効時間が切れる前に、有効時間を延長するため の手続きを実行しなければなりません。 プレフィックス情報はタイマー管理されており、肩効時 間の延長が必要になると mip6-prefix-send-mps() 関数 カ鮃び出されます。 static int 214 215 mip6—prefix—send—mps (mpfx) インターフェイスに保持されている対応付け更新エントリ を調べています。 225 行目の mip6-bu 」 ist-find-home- registration() は、第 2 引数で渡されたホームアドレスに 対応するホーム登録ェントリを検索する関数です。 mip6- prefix-send-mps() に渡されたプレフィックス情報に対応 するホームアドレスは、 mpfx->mpfx-haddr に格納され ていますから、そのアドレスに対応するホーム登録工ント リがあるかどうかを調べます。工ントリがあれば、 mip6- icmp6-mp-sol-output() でモバイル・プレフィックス要 求メッセージを送信します。工ントリがなければ、メッセ ージを送信することはできません。 693 int 694 mip6—icmp6—mp—s01—output (haddr , haaddr) 695 696 { struct in6_addr *haddr , *haaddr ; 216 217 { struct mip6-prefix *mpfx; mip6-prefix-send-mps() はモバイル・プレフィックス 要求メッセージを送信する関数です。この関数は、引数と して渡されたプレフィックス情報に関する最新情報をホー ム・エージェントに要求します。引数 mpfx には、更新 対象となる mip6-prefix 構造体へのポインタが設疋され ます。 モバイル・プレフィックス要求メッセージは、移動ノー ドのホームアドレスを始点アドレスとし、終点アドレスに はホーム・エージェントのアドレスか第殳定されなければな りません。ホームアドレスを利用するため、ホーム登録処 理がすでに完了していることが条件になります。 図 1 の 222 行目のループで各ホームネットワーク・イ ンターフェイス (hif-softc 構造体 ) をたどり、それぞれの 94 mip6-icmp6-mp-sol-output() はモノヾイル・プレフィ ックス要求メッセージを構築し、送信します。この関数は 2 つの引数をもちます。 haddr はメッセージを送信する際 の始点アドレスとなるホームアドレス、 haaddr は終点ア ドレスとなるホーム・エージェントのアドレスです。 712 sc = hif—list—find—withhaddr(haddr) ; 713 if ()c = = NULL) { 719 720 } return ( 0 ) ; 712 ~ 720 行目で、ホームアドレスに対応するホームネ ットワーク・インターフェイスを検索します。対応するホ ームネットワーク・インターフェイスがみつからない場合、 haddr で指定されたホームアドレスは有効な値ではありま せん。 UNIX MAGAZINE 2005. 12

7. UNIX MAGAZINE 2005年12月号

連載 / ロボットのある暮らし リスト 2 ネットワークキ / / ネットワークの準備 / / CCtr1Socket は CAsyncSocket の派生クラス m-pSocCtr1 = new CCtr1Socket ( ) ; 図 2 コックピット・プログラム ( 暫定版 ) if if (m—pSocCtr1—>Create(0, SOCK-DGRAM, FD-READ, NULL) / / 工ラー処理 (m—pSocCtr1—>Connect (strHost , DEFAULT-CTRL-PORT) return ー 1 ; / / 工ラー処理 return ー 1 ; / / 起動メッセージを送信 m—pSocCtr1—>Send(buf , strlen(buf) strcpy(buf , "HELLO\n") ; ファイ外 ( 日編集 ( 印制表示 基物ヂ可 ~ / レディ ステータス表示 映像系 ネットワーり接読 制用末 笥区 ^ 非プ凹 ロポト制師 れはロポット側からデータを受信することになるので、デ ータ受信機能も用意した ( 図 3 ) 。 一般に送信と受信は非同期におこなわれるため、普通な ら、プロセスを独立させるか複数のスレッドを使うなどし て、送信用の実行の流れと受信用の実行の流れに分けるこ とになる。あるいは、 select のようなポーリング機能を使 い、随時送受信処理をおこなう。 こでは、 CAsyncSocket クラスの通知機能を使って、 もっと簡単に送受信の並行処理をおこなっている。通知機 能とは、なんらかの条件カった ( たとえば送信可能にな ったり、データを受信した ) ときに、適当な関数が自動的に 呼び出されるという機能である。 CAsyncSocket クラス では、 create でソケットの準備をする際にフラグを指定 することで、この機能力吏える。 まず、通知関数に独自の機能を記述するために、 CA- syncsocket から派生した独自のクラスを作成する ( プロ UNIX MAGAZINE 2005. 12 図 3 PC 側のプログラムの構造 メッセージループ んだら、ロポット側のセンサーの情報、ビデオカメラで撮 のコマンドである。また、ある程度プログラムの作成が進 るのは、ジョイスティックの操作情報と、その他の制御用 御をおこなうというものだ。 W ⅲ d 。 ws 側から送られてく 由で送信されてきたコマンドにもとづいて、ロボットの制 ロポット側の制御プログラムの機能は、ネットワーク経 ロポットテーモン 1 号 ドウに表示しているだけである ) 。 い ( 現状では、たんに受信メッセージをデバッグ・ウイン Receive をオーバーライドし、必要な処理を言杢すればよ ンバー関数カ剛乎び出される。あとは、派生クラス中で On- 受信したときに、自動的に OnReceive という通知用のメ グを指定して Create 関数を呼び出す。これで、データを CCtrISocket を使っている ) 。そして、 FD-READ フラ グラム中のソケット関連処理は、すべてこの派生クラス 163

8. UNIX MAGAZINE 2005年12月号

■ビジネスルールの適用 代替ラベル : ドライバーの {this} 契約時の年齢 Services Description Language) をインポートする 変換 方法である。すでにモデルが作成されていれば、そのま ' ' DayUtil.GetAge({this}. driver. birthday, ま使える。もう 1 つ、ウイザードを用いて定義していく {this}. contractDay)" 方法もある。モデル実装のない設計段階や、モデル実装 をインポートしたあとで仮想クラスや仮想メソッドを作 上例の、、 { this } " は、インスタンス・オプジェクトを 成する場合は、こちらを使う。 現す変数 ( 、、ドライバー 1 " や、、保険構成 1 " など ) に置 プロトタイピング手法によるスパイラルな開発では、 き換わる。 まず基本モデルを設計し、 Java クラスまたは XSD を また、 insurance. model. Insurance#driverAgeAt 作って BOM ヘインポートする。モデルを変更した場 ContractDay には変換属性があるようにイ反想属性であ 合は、それに応じて BOM を更新する機能がある。 る。実装レベルでは存在していない。 年齢のような属性は通常は生年月日から求めるが、実 代替ラベルと変換 装レベルでメソッドとしてイ尉寺してもよいし、このよう ビジネスルールの言当では、クラスやメソッドに、、代 に BOM で仮想的に定義してもよい。 替ラベル " や、、変換 " の属性を設定する。代替ラベルは、 クラスに変換属性があるのは、そのクラスをどのよ 日本語をはじめとする自然言語へのマッピングになる。 うにマッチングさせるかを指定するためである。たとえ そして、仮想クラスや仮想メソッドに、、変換 " 属性で変 ば、ビジネスルールにドライバーと保険構成があれば、 換方法を設定する。 暗黙裡に見積り対象のドライバーと保険構成を結びつけ たとえば、以下のようにして定義する ( 下記は抜枠で る。これはビジネスルールのなかで明示的に言当しても ある ) 。 よいが、業務ユーザーにとって、、当り前 " のルールであれ ば、暗黙的に書いてビジネスルールを簡潔にすることが ・ msurance. model.Driver 代替ラベル : ドライバー できる。 変換 ( 誌面の都合上、で折り返しています。以下同 ビジネスルールを言しながら、このように BOM を 様 ) ・ 磨く、、リファクタリング " をおこなう。ビジネスルール を書くうえで重要なのは、実行時の動作を念頭におき、プ insurance. model. Driver() from - {insurance. model. Quote}. getDriver()' ログラム的にルールを記述しないことだ。あくまでも、 ◇ getLicenseType() 業務ユーザーから出てきた自然言語による言当に従って 型 : String ビジネスルールを書いていくのである。言古できなけれ 代替ラベル : {this} の免許タイプ ば、 BOM カ坏十分ということである。その場合は、仮 ◇ getBirthday() 想クラスやイ反想メソッド、実装レベルのクラス、メソッ 型 : Date ドを追加 / 変更し、モデルを修正していく BOM を変 更するだけなら、 , 、イルやビ、ドなと : の作業は不要 代替ラベル : {this} の誕生日 ・ insurance. model.lnsurance である。 代替ラベル : 保険構成 上記の例では、代替ラベル属性に直接日本語で指定し ているが、、、 & key " のように、、 & " で始まるメッセージキ 変換 insurance. 1110deI. lnsurance() , ・ ーを指定し、言語ごとに外部のメッセージ・ファイルを {insurance. model. Qt10te}. 利用してもよい。 ◇ contractDay ビジネスルールの記述例 型・ Date ビジネスルール管理環境での例を図 2 に示す。 代替ラベル : {this} の契約年月日 BOM のボキャプラリがプルダウン・メニューに表示 ◇ driverAgeAtContractDay され、マウスでルールを言当していくことができる。 升リ UNIX MAGAZINE 2005. 12 24

9. UNIX MAGAZINE 2005年12月号

図 1 2 つのプログラムの旨 ジョイスティックのデータ Windows 上の 制御プログラム ・ジョイスティック のデータ ・各種のコマンド ・ UDP でデータを送信 を取得 ・ジョイスティック・データ ロ サーボ制御 ロポット側の 制御プログラム ・各種コマンドの処理 ・動作角度の算出 ・操作するサーボの判定 を受信 ・ジョイスティック・テータ も処理されていない情報である ( 次回説明する予定だが、ハ ットスイッチ関連の情報だけはコックピット・プログラム で多少の処理をおこなっている。しかし、これによって失 われる生データはない ) 。ロボットデーモン 1 号プログラ ムは、これらの値から、個々の関節のサーボをどのように 動かすかを判定、算出し、その制御をおこなう ( 図 1 ) 。し たがって、操作内容に対してロボットの挙動を変える場合 は、ロポット側のプログラムを変更することになる。 コックピット・プログラムは、ほかにもいくつかの制御 コマンドをロボットに送るが、これも制御用プロトコルに 合わせてフォーマットし、その文字列をロポットに送るだ けだ。それを解釈して適切な処理をおこなうのは、ロポッ ジョイスティックの処理 ト側の仕事である。 UNIX MAGAZINE 2005. 12 人間の認識能力やロポットの動作速度などを考えれば、 CPU パワーやネットワーク帯域を消費することになる。 する処理の繰返しを単純なループで構成すると、無意味に ジョイスティック・データを読み出し、ロポットに送信 の手川頁は前回紹介した。 ラムでジョイスティックを認識し、データを取得するため をロボットに送信する作業を繰り返す。 Windows プログ ュールを介してジョイスティックの情報を読み取り、それ コックピット・プログラムは、 DirectInput というモジ 連載 / ロボットのある暮らし トレスでおこなっているので、エラー処理などはほとんど スト 1 ) 。前回説明したように、ネットワーク通信はステー Send コマンドを使って UDP で送出しているだけだ ( リ 当な文字列にフォーマットし、 CAsyncSocket クラスの ョイスティックのデータを読み出す関数を呼び出して、適 述するだけでよい。タイマールーチンの内容は簡単で、ジ イマーの設疋、タイマールーチンの言、最後の後始末を記 このような構造のため、プログラマーのレベルでは、タ で、ほかの処理の途中でタイマー割込みが起こる心配はな の処理を扱うことができる。イベントは順に処理されるの タンのクリックなどと同じようなかたちでタイマー割込み 満了はメッセージで通知されるので、メニューの選択やポ なっている。タイマー割込みも例外ではなく、タイマーの れのメッセージに対してなんらかの処理をおこなう構造に グラムに通知される。 Windows のプログラムは、それぞ 動型であり、各種アクションはメッセージのかたちでプロ 実現できる。 Windows プログラムは基本的にイベント駆 しかし Windows では、この種の処理をもっと安直に 制御をおこなう必要がある。 うに、データアクセスやコードの実行に関して、適宜排他 インストリームとハンドラのあいだで干渉カ起こらないよ ハンドラは非同期に起動する。このとき、実行しているメ UNIX の場合、インターバル・タイマーによるシグナル ればよい。 データを読み出し、ネットワーク経由でロボットに送信す なる。したがって、この関数のなかでジョイスティックの れば、その時間間隔で関数が定期的に呼び出されるように ( ミリ秒単位 ) とハンドラ関数を指定してタイマーを設定す マー機能を利用して繰返し処理を実現している。時間間隔 めコックピット・プログラムでは、 W ⅲ dows のもっタイ の処理 ) をおこなうことも考えなければならない。そのた 実現できるが、合間にほかの処理 ( メニューやボタンなど この時間調整は、プログラム中でスリープする方法でも つもりだ。 時間間隔で処理をおこなえばいいかは、実験して確かめる この処理を繰り返せばよいことになる。実際にどれだけの 十分だろう。つまり、 100 ミリ秒から数百ミリ秒の間隔で の処理はせいぜい 1 秒間に数回ないし 10 回もおこなえば ない。 161

10. UNIX MAGAZINE 2005年12月号

ー 0 連載 / Linux のツールたち 図 8 リカバリー DVD のブート画面 日 00t れ、 0 ・日謝、 d 0 に rnstallation lnstallation ー仙 PI 0 曲一 lnstaliation - Safe settings or リ Test スやネットマスクなどを設定しないとさきに進めないので、 適当な値を指定します。すると、レスキュー ・システムの イメージがメモリに展開され、次のようなログイン・プロ ンプトカ観れます。下線部のように、、 ro 。 t " と入力してリ ターンキーを叩くと、シェルが起動してレスキュー・シス テムカ駛えるようになります。 Rescue login: root Rescue:- # これ以降のリカバリー手順は以下のとおりです。 1. HDD のパーティション作成 fdisk コマンドで HDD にパーティションを作成しま す (fdisk の使い方の詳細は、オンライン・マニュアル fdisk(8) または 2004 年 7 月号を参照してください ) 。 今回は、バックアップした SUSE93 のパーティション 構成に合わせて、以下の 2 つのパーティションを作成し ました ( いずれも基本バーティション ) 。 ・ sdal : スワッフ。領域 (Linux Swap) 、約 500MB ・ sda2 : Linux7S—ティション、約 3.5GB 2. スワッフ。領域と新規パーティションの初期化 mkswap と mkreiserfs コマンドを図 10 のように実 行し、スワップ領域 ( sdal ) と Linux パーティション (sda2) を初期化します。 ReiserFS 以外のファイルシステムで初期化したい場 合は、各ファイルシステム用の初期化コマンドを実行 します。たとえば、 ext3 ファイルシステムの場合は mkfs. ext3 コマンドを使います。 3. DVD と新規パーティションのマウント リカバリー DVD13 とリストア先となるパーティション (sda2) を、レスキュー・システムにマウントします。次 の例では、それぞれ /media/cdrorn14 と /mnt にマウン トしています。 mount —t iS09660 /dev/hdc /media/cdrom mount /dev/sda2 /mnt 4. バックアップ・データのリストア 13 デフォルトでは、イ反想マシンの CD/DVD ドライプはセカンダリ IDE チャネルのマスタードライプなので、対応するデバイス名は "hdc" になり ます。 14 mount 実行時に read-only オプション← 0 (o) を帛しないと、、読 込み専用でマウントする " という警告メッセージカ俵示されます ( マウント は問題なくおこなえます ) 。 0 樞町、を′町いすⅳ釧 図 9 手動セットアップの初其月画面 設ーけ 0 れは 〉〉 ) L 川 x c り 1.8.6 ( e れに一 2 .6 . 11 . 4 ー 23 に「 t ) くくく 3 に t い ngs S リゞ te い 0 第は t ー 0 れ 区 e れに一 od 社ー 0 ( Harduare Dr ー uers ) リ 0 「一「リー st はー 00 CD ー 0 員 / 000 EJect CD 主メれ 0 boot ~ 0 リ er 可「 3 t r t い一 s t ー la t 0 n 0 r S s t に Back の、、 Rescue System" を選択します。 するとカーネルカ毓み込まれ、 IP アドレスを DHCP で 取得しようとします。私の環境では VMware の DHCP サーバーを無効にしているため、 DHCP リクエストがタイ ムアウトするまで待たされ、、、インストールのソースがみつ からないので、手動でセットアップしなさい " という未の 警告メッセージが表示されました。 「 OS をインストールするわけじゃないのに ・・・」とっ ぶやきながらリターンキーを叩くと、インストールに使 用する言語とキーボードの配列を訊かれます。どちらも 、、 English" を選択 12 すると、手動セットアップの初期画面 ( 図 9 ) が表示されます。ここで、、 Start lnstallation or System" を選び、さらに次のメニューで、、 Start Rescue System" を選びます。 レスキュー・システムのソースメディアとして CD- ROM を選択し、ようやくレスキュー・システムか起動す ・・と思ったのですが、、、 DHCP で自動定するか ? " る、 という質問が表示されます。今回はネットワークを使う必 要はありませんが、 DHCP を利用しない場合は IP アドレ 12 日イ吾キーポードを使っている場合は、キーポード酉改リは "Japanese" を 選ぶとといいでしよう。 173 UNIX MAGAZINE 2005. 12