000 - みる会図書館


検索対象: UNIX MAGAZINE 2004年4月号
204件見つかりました。

1. UNIX MAGAZINE 2004年4月号

連載 /FreeBSD のブートプロセスをみる 3 ーの ; 0 , # trap 2065 : 2064 : 2063 : 2062 : 2061 : 2060 : 2059 : 2058 : 2057 : 2056 : 2055 : 2054 : 2053 : 2052 : 2051 : 2050 : 2049 : 2048 : 2047 : 2046 : 2045 : 2044 : 2043 : 2042 : 2041 : 2040 : 2039 : 2038 : 2037 : 2036 : 2035 : 2034 : 2033 : 2032 : 2031 : 2030 : 2029 : 2028 : 2027 : 2026 : 2025 : 2024 : 2023 : 2022 : 2021 : 2020 : 2019 : 2018 : 1469 1468 : 1467 : 1466 : 1465 : 1464 : 1463 : 1462 : 1461 : 1P—>gd—p = 1 ; 1P->gd—100ffset = selector = ip—>gd—stkcpy = 0 ; XX = 0 ; xp->gd-type = typ ; lp—>gd—dpl = dpl ; ap—>gd—hioffset = xp->gd- xp—>gd— (int) func ; selec ; ((int)func)>>16 ・ 図 10 割込みゲート / トラップゲート / タスクゲート・デスクリプ (a) 害みゲート・テスクリプタ タの構造 32 オフセット ( 31...16 ) セグメント・セレクタ 484746454443424140393837 res オフセット ( 15...0 ) PDPL 0 1 1 1 0 0 0 0 (b) 63 31 31 トラップゲート・デスクリプタ 士 or (x = 0 ; x く 129 ; x + + ) setidt(), &Xrsvd, Oxf, 0 , GCODE—SEL くく 3 ー 0 ) ; オフセット ( 31 … 16 ) セグメント・セレクタ 4847464544434241 40 3938 37 P DPL 0 1 1 1 1 0 0 0 オフセット ( 15...0 ) setidt ( 0 , &Xdiv, GCODE_SEL くく 3 setidt ( 1 , &Xdbg, GCODE_SEL くく 3 setidt(), &Xnmi, GCODE_SEL くく 3 setidt(), &Xbpt, GCODE_SEL くく 3 setidt(), &Xof1, GCODE_SEL くく 3 setidt ( 5 , &Xbnd, GCODE_SEL くく 3 setidt(), &Xi11, GCODE_SEL くく 3 setidt(), &Xdna, GCODE_SEL くく 3 setidt ( 8 , 0 , 0X5 , 0xf , Oxf , 0xf , Oxf , 0xe, 0xf , 0xe Oxf , ーの ; 0 , # trap 3 , # 3 , # trap 0 , # 0 , # trap 0 , # ーの ; 0 , # task int errupt int errupt trap trap # trap # trap # int errupt # trap # trap 0 , # trap # trap # trap # trap trap # trap # trap ( c ) タスクゲート・デスクリプタ 63 res TSS セグメント・セレクタ 31 4847464544434241 4039 37 P PL 0 0 1 0 1 「 es 0 32 res 0 32 res 0 GPAN 工 C_SEL くく 3 ー 0 ) ; setidt(), &Xfpusegm, 0xf , 0 , setidt(ll, &Xmissing, Oxf, GCODE_SEL くく 3 ー 0 ) ; setidt(10, &Xtss, Oxf, 0 , GCODE_SEL くく 3 ー 0 ) ; GCODE—SEL くく 3 ー 0 ) ; setidt(19, &Xxmm, GCODE_SEL くく 3 ー 0 ) ; setidt(18, &Xmchk, GCODE_SEL くく 3 ー 0 ) ; setidt(17, &Xa1ign, GCODE_SEL くく 3 ー 0 ) ; setidt(16, &Xfpu, GCODE_SEL くく 3 ー 0 ) ; setidt(15, &Xrsvd, GCODE_SEL くく setidt ( 14 , &Xpage , GCODE_SEL くく 3 ー 0 ) ; setidt ( 13 , &Xprot, GCODE_SEL くく 3 ー 0 ) ; setidt(12, &Xstk, GCODE_SEL くく 3 ー 0 ) ; Oxf , Oxf , Oxe , Oxf , Oxf , Oxf , Oxf , 0xf , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , setidt(Ox80, &XintOx80_sysca11, lidt (&r—idt) ; r—idt . rd-base = (int) idt ; r—idt . rd—limit = sizeof(idt0) Oxf , 3 , GCODE_SEL くく 3 ー 0 ) ; UNIX MAGAZINE 2004.4 の領域です。割込み / 例外のべクタ番号は全部で 256 個あ 1 , 232 行目で宣言している配列は、新たに作成する IDT りますが、 SMP に対応していないカーネルでは 0 番から 128 番までのテープルを用意します 3 。 割込みと例外のべクタ番号 0 から 31 までは lntel の 予約領域で、それぞれ次ページの表 2 に示す未がありま す。 2 , 021 ~ 2 , 059 行目は、この仕様に従ってべクタに対す るハンドラを IDT に登録します。 2 , 060 ~ 2 , 061 行目で 登録している Xint0x80-syscall は、システムコールを実 装するハンドラです。ここで登録している割込みハンドラ は、すべて i386/i386/exception. s に定義されています。 1 , 451 ~ 1 , 469 行目の setidt() は、 IDT に登録するゲ ート・デスクリプタを作成するサプルーチンです。 IDT に登録するエントリ ( ゲート・デスクリプタ ) は、ハ ンドラのアドレスや実行権限などの属性を設定するデータ 構造です。ゲート・デスクリプタには以下の 3 つのタイプ があり、 FreeBSD ではこれらをすべて使います ( 図 10 ) 。 ・タスクゲート・デスクリプタ ( 05H ) ・割込みゲート・デスクリプタ (OEH) ・トラップゲート・デスクリプタ (()FH) 上記の括弧内は、 setidt() の第 3 引数に指定する値です。 割込みゲートとトラップゲートの基本的な違いは、ハン ドラを呼び出すときの IF フラグの変化です。割込みゲー トは、ハンドラを呼び出すときに IF フラグをクリアし、割 3 コンパイル・オプションに SMP か APIC_IO を指定した場合は、 255 番までのテープルを作成します。 167

2. UNIX MAGAZINE 2004年4月号

デバッガの基礎知識 図 24 メモリ内容窈忍 ( 2 ) (gdb) x / 12 &p 0xbfffe6bc : 0xbfffe6cc: Oxbfffe6dc : (gdb) 0X080483ae 0X42015574 9X0043424 長 0X42130a14 0X00000001 0X4000C80 三 0X40015360 0xbfffe724 特集 0xbfffe72c 0xbfffe6f8 0xbfffe6d8 図 25 メモリ内容忍 ( 3 ) (gdb) x/12b &buf [ 0 ] 0xbfffe6c0: 0xbfffe6c8: (gdb) : 0X41 三 0xd8 9X42 0xe6 三 0X43 : 0xff : 0X00 三 0xbf 三 0X60 : 0xc6 0X00 0X40 図 26 メモリ上に石呆された令或 ( 3 ) 変数 p として 確保された領域 変数 buf として 確保された領域 意味のない値 0X41 0X42 0X43 0X00 意味のない値 アドレス 0xbfffe6bc 0xbfffe6c0 残っています ( 図 26 ) 。もちろん、この値には未はあり ません。変数 p にはまだ何も代入されていないので、 p が 確保されているアドレス 0xbfffe6bc の値に変化はありま せん。 それでは、ふたたびもう 1 行実行して、同じメモリ領域 の内容を確認してみます ( 図 27 ) 。さきほど、メモリサイ ズの単位としてバイト (b) を指定したので、これ以降のメ モリサイズの指定はデフォルトでバイトと解釈されるよう UN 工 X MAGAZ 工 NE 2004.4 が設定されたのが分かります。実際には、、 p = buf" とい すると、今度は変数 p の領域 ( 実線で囲った部分ロ値 リサイズの単位としてワード (w) を指定します。 になります。これをワード単位での表示に戻すには、 メモ う文を実行したのですから、 p という変数が buf のアドレ 47 デバッガは、もうすこし複雑なプログラムがどのように プログラムやライブラリの挙動を調べる たでしようか。 どのような値が設定されているのかを実感することができ どういう末をもっているのか、ポインタという変数には こまでの説明で、プログラムで変数を宣言することが たのかカ寉認できます。 これで、それぞれの変数がどのような型として宣言され (gdb) type = char * (gdb) ptype p type char [ 5 ] (gdb) ptype buf ように表示されます。 よび p に対して ptype コマンドを実行してみると、次の かを調べるには ptype コマンドを使います。変数 buf お 変数の値を調べるのではなく、変数がどのような型なの 列 ABC が入っていることカ認できます。 り、その内容は文字列 ABC を指していて、 buf には文字 ポインタ p には buf のアドレス 0xbfffe6cO が入ってお (gdb) $ 4 = "ABC\OOO' " (gdb) p buf $ 3 = 0xbfffe6c0 "ABC" (gdb) p p この時点での、変数 buf と p の値も表示してみましよう。 ( 図 28 ) 。 の先頭アドレス 0xbfffe6c0 が入ったことか確認できます スを指すことになったわけです。事実、 p の領域には buf

3. UNIX MAGAZINE 2004年4月号

ワークステーションのおとーー 0 画面 2 NetCfgInstanceID 万イル ( 日編集表示 ( ) お知こ入り ( ヘルプ但 ) ・一コ ( 40 ] 6E968 ・ E3254 ICE ・ BF ( ト 080028 ィー名前 ・一レジス工ディク ・ ! 」 ( 40 ] 5E969 ・ E325 ・ ( E ・ BF ( ト 08002B ・一コ ( 4035E96 キ E32541 ( E F ( ト 0 師 028 ・一コ ( 4035E96B ・ E325 ・・ BF ロ・ 08002g 第一コ { 4036E900E3254 ICE-BFCI ・ 080028 第一」 ( 4036E 60 ・ E325 ・ 11 ( E ・ BFC : ・ 0 師 02B ・一」 3D36E96E ・ E325 ・ 11 ( E ・ BF ( 1 ・ 080028 ・ ( コ ( 4036E96F ・ E32541 ・ BF ( : ・ 08002 日 - ーコ 3036E970 モ 3254 : ( E ・ 3F ( ト 080028 ( 4036E9 フト E ] 254 : 〔 E ・ BFC ト 08002B 一コ ( 4036E972 ・ E ] 25 ・・ BF ( ト 08002 ツ ・一コ 0 5 ・一コ 0014 第一コ 00 ロ 一コ 00 に 田こ」 00 い ・一コ 0 衄 0 ・コ 00 的 ・コ 0g8 ・一コ 0007 ・ロ 0006 ・こ」 0005 ・ロ 0004 国コ 00 の ・ロ 0002 ・一コ 000 : 、」コ 0000 、 ( 既定 ) @BusType ー ( れ act 部に 5 ( 00 つ 00 ~ 吠 一 D 解 e の曾 引鵞 0 を D を は 0 解粃 V を On [ ln や社 h 2U00 で 物 : ( h 国 D 報 ( 引 d M d 朝 , 1 [ ~ 0 400 保 55 扣 5 い上 6 ー SZ REG_SZ REG-OWORD REG_SZ REG_SZ REG_BINARY REG—SZ G ー立 REG_SZ REG_SZ REG_SZ REG_SZ 能 6 ー SZ G ー綻 5 ー SZ 0 区 データ ( 値 0 定なし ) 0X00000004 ( 4 ) 当め 00 7 ・ト 20 い 00 80 62 ( 5 ( 001 CI 0 : M0050 を L00P03 ( k Adapter 5. k2535.0 02 物 00 「 MSLOOP. 0 ま . uT 0 ( WAEAB75 ・ 7A E イ OFE ・ 8378 ・ S9A6FE ー 2 9F3 ) M00 駒を マイコンビュータ H Y ー [ 0 ( AL ー t4ACHIN SYST 日物 ( い健 ( on び 06 を ( on 0 ( 5 ( 4D36E972 、 E325 ・ 11 ( E ・ ( ト 08002bE10 引 8 洋 0016 画面 3 Bind 、 Export 、 Route から餘 方イル旧集 ( 印表〒 ( Y ) お知こ入りヘルス印 ・こ」 NDIS 第一コⅱ d 0 ・一」 NDP?OW ーコ獸引 05 こ」 EE' し 01 こコ ( 奇 ・ロ NetDDE を一コ lletDDEdsdm こい物 000 ・匚」 Ne : 0 0 ・こ」 NetSvc ・〔」 N に : 394 、こ ] NISSERV ・一コⅢ 5 リ M 、ロロ 11 ・コ NPfs ・一」 NS ( 沢 OA ・ロ Nfs 国一コ NtLmS9 ・ロ utmssvc ・こ」 tlug 気房ス籾工デイタ 匿」 0 区 当 Expo 區い物 0 R 。心 REG_SZ REG—MULTLSZ 6 ー MUL - REG - 日川 A REG—MULTI—SZ (f 直定なし ) 1 T 、冖 T ( 00 ま“ 0F9050B0 ・ 01284D5 ト ADD.. 01 0601 0901 能 0 : 0b01 0 ( 01 01 00 01. 、 D 文引 05 」 T ー T ( 026-0F995080 ・ 0. 第 0 ( 霹を出 1 一丁 ( 006 」フ F 印 80 ・ 0128705 ド・、、 マイコンビュー HKEY ー L004L - MA 〔 H 田 SYSTE トⅣ〔し健 ( on び 05 を S をハをを : 0 し 1 0 を を選び、 [ 次へ ] ボタンをクリックする。 5. 、、共通ハードウェアの種類 " の一覧から、、、ネットワーク アダブタ " をダカレクリックする。 150 back Adapter の 139 番ポートを開放する " はちょっと手 ただし、さきほどの手川頁の 3 番目、、、 Microsoft Loop- じようにすればよいでしよう。 定も、通常のネットワーク・インターフェイスの場合と同 は、とくに難しいところはありません。 IP アドレスの設 Microsoft Loopback Adapter のインストール自体 了 ] ボタンをクリックする。 7. 現れた画面で [ 次へ ] ボタンをクリックし、さらに院 Ad 叩 ter " をダブルクリックする。 ワークアダブタ " の一覧から、、 Microsoft Loopback 6. 、、製造元 " の一覧から、、 Microsoft" を選び、、、ネット 間がかかります。 Lef さんの Web ページに詳しい手川頁が 書かれていますが、こちらもすこし補足しておきましよう。 1. Microsoft Loopback Adapter Driver の ID を調 べる。 まずレジストリ・エデイタ (regedit. exe) を起動し、 HKEY_LOCAL_MACHINE*SYSTEM*CurrentContr01Set* Contr01*C1ass の下で、 Microsoft Loopback Adapter" をキーワー ドに検索します。すると、、、 DriverDesc" の値が、、 Mi- crosoft Loopback Adapter" になっているところがみ つかるはずです。その近くに、、 NetCfgInstanceId" と いう項目がありますが、その値が求めている ID になり ます。私のノート PC では、画面 2 のようになってい UNIX MAGAZINE 2004.4

4. UNIX MAGAZINE 2004年4月号

連載 /UNIX Communication Notes 190 図 2 Mac OS X 10.3 での WebDAV の初期言綻 ( a ) 最初は、、ネットワーク " ど、 HD " だけ 第トを 0 を ( d ) 認証情報を入力 WebDAV ファイルシステムの認証 まの URL のサーバにアクセスするためのユ -- ザ名とバス ワードを人力してくださいに h 0 : / 92 は 68253 は 0 レ り・、領城 - Pa 弱 WO ′ dfO ′ OA に 0 、 % ユーザ名とバスワードは安全に送備されませんを 名前 5 リ gu 「し バスワード M ま 0 第 0 、 ネットワ - ク こバスワードを記する ( キーチェーンに追加 ) (e) dav " という名前で WebDAV サーバーがマウントされる 第日 0 0009 ( b ) 移動→ーバへ接続 ... " を選択 物日 0 ′ファイル 編第表示 ウインドウヘルプ 000 4 物囲 , 戻る 内しているノ : ! ルっ コンビュータ 0 第 ( ↑ホーム 0 第 H ・ネットワーク 0 XK 0 0 、 k ヘアプリケーション 0 XA にユーティリティ 0 興 U 最近使ったフォルダ フォルダへ移釚 . M 95 れ HO M 95hH0 第 5 OP Suguru 0 ー e 、 A00 ⅱ ( 0 れ、 ( 0n12 、 ネットワーク ットワーク d . 三 . い、を ( 山瓶に b n ( h 0 代「引 onOl.p 引 b 健バ i0002 d ′ 純 bve 再 9n0 引 p : ′ A00 3000 、 ( c ) WebDAV サーバーのアドレスを指定 サー、バへ接続 サーバアドレス : http.//webdav.nalstjp/dav よくうサ ~ バ : Ap がに ~ 0005 こ 9 こ dav 取り除く cadaver は、 ftp コマンドと同様な感覚で使うことがで ・ http://www.webdav.org/cadaver きる。図 3 を見てほしい。 cadaver を起動して help で から入手できる。執筆時の最新版は 0.22.0 で、ファイル コマンドー覧を表示させると、 ftp とそっくりな部分があ 名は cadaver-(). 22.0. tar. gz である。 ることに気づくだろう。サーバーへのアクセスは open 、 インストールは、基本的に configure 、 make 、 make アクセス終了は close 、サーバーからのファイルの入手は install を順に実行するだけである。なお、 cadaver では get 、 mget 、サーノヾーー、のファイルの車幻医は put 、 mput OpenSSL や XML パーザライプラリ (expat) などを使 コマンドを使えばよい。 WebDAV サーバー ( この例では うので、システムに入っていなけれは事前に導入しておこ http://webdav.naist.jp/dav/) にアクセスすると、ユー ザー名とパスワードの入力による認証処理をおこなったあ と、サーバー上のファイル一覧を見たり、ファイルをダウ ンロードしたりすることができる。 現在のようにシステムカ夏雑になってくると、ソフトウェアや ライプラリの相互依存関係を手作業で管理するのは大仕事である。 そのため、 Linux や BSD 系 UNIX ではパッケージを用いた 管理が - ヨ殳的になっている。この機能を使えば、ソースからコン パイルする場合も、必要なライプラリを事前に導入するところまで 面倒をみてくれる。これほど便利なのだから、いったん使ったら やめられなくなるのも当り前かもしれない。 cadaver は未なツールだが、コマンドラインで使えるのは やはりイリである。 UNIX システムで WebDAV クライアント を利用したいのなら、 cadaver の導入を強くお勧めする。 57 UNIX MAGAZINE 2004.4

5. UNIX MAGAZINE 2004年4月号

特集 テパッガの基礎知識 図 27 メモ男或の内容 Di 忍 (gdb) s printf("%s\n", p) ; 10 (gdb) x/12w &p 0xbfffe6bc : : 0X00434241 : 0xbfffe6cc: 0X080483ae 0X42130a14 0xbfffe6dc : 0X42015574 0X00000001 (gdb) 0X4000C660 三 0X40015360 0xbfffe724 0xbfffe6d8 0xbfffe6f8 0xbfffe72c 図 28 メモリ上に石呆された帛或 ( 4 ) % gdb a. out GNU gdb Red Hat Linux ( 5 .3post ー 0.20021129.18rh) Copyright 2003 Free Software Foundation , lnc . (gdb) さきほどと同じく ma ⅲでプレークポイントを設定し、 1 つずっ動作を確認していきます。 (gdb) b main Breakpoint 1 at 0X80483d8 : file samp1e4. c,=+ line 17 . (gdb) run Starting program: /Programs/Samp1e4/a. out Breakpoint 1 , main ( ) at samp1e4. c : 17 17 TLIST* base = NULL; ( gdb ) まずは、動作の大枠を確認します。リストの頁を表す base 変数の値を確認しましよう。 (gdb) n base = addCe11("ce11 A" 19 1 , base) ; (gdb) p *base Cannot access memory at address 0X0 動作するかを調べるときにも便利です。 この時点では、 base 変数は NULL で初期化されている 以下では、単純な 1 方向のリスト構造を扱うプログラム ので、その内容はまだ確認できません。 を例に説明しましよう。 もう 1 行実行すると addCeII 関数が実行され、その戻 リスト構造は、実用的なプログラムを書き始めると、イ り値で base 変数に何かの値か轂定されるようです ヤというほどお目にかかるはずです。しかし、最初のうち とりあえずは addcell 関数の細か 0 、挙動を調ミるのは は、動作カ吩かりにくいものの筆頭でもあります。ここで あとまわしにして、さきに addCell 関数を実行すると何が はデバッガを使い、どのようにリストカ胙られていくのか 起こるのかをみてみます。ステッフ。実行するときに、関数 をみていきましよう。 内部に制御を移さないようにするには next コマンドを利 図 29 の sample4. c は、単純なリスト構造を使ったプロ 用するのでした。 next コマンドを使い、一気に 19 行目、 グラムです。 つまり addCeII 関数を実行して base 変数にどのような値 リスト構造 tlist は、 1 つのセルに名前 (name) と番号 か轂定されるのかをみてみます。 (number) 、そして、次のセルを指すポインタ (next) をも つ構造になっています。 (gdb) n まず、 gdb でこのプログラムの動作をざっとみてみます。 addCeII("ce11 B" 2 , base) ; 20 base (gdb) p base % gcc —g samp1e4. c (TLIST * ) 0X8049750 アドレス 0xbfffe6bc 0xbfffe6c0 変数 p として 確保された領域 0xbfffe6c0 0X41 0X42 0X43 0X00 0X60 ( 意味のない値 ) 変数 buf として 確保された領域 48 UN 工 X MAGAZ 工 NE 2004.4

6. UNIX MAGAZINE 2004年4月号

連載 /FreeBSD のブートプロセスをみる 図 3 kenv コマンドの実彳デ列 LINES="24" acpi—10ad='tYESt' bootfile="kernel" console="vidconsole" currdev="disklsla: " hint . acpi . 0 . oem="PTLTD unsigned ssd—limit unsigned ssd—xx : 4 1391 : } ; 図 4 63 図 5 セグメント・デスクリプタ 484746454443 4039 5655 54 535251 0> リミット 32 べース ( 31...24 ) GDE< ( 19...16 ) P DPLS タイプ A べース ( 23 … 16 ) べース ( 15...0 ) リミット ( 15...0 ) hint . acpi . 0 . reviSIon="1" hint . acpi . 0 . rsdt="Ox01efaf80" 内容か環境変数としてカーネルのなかに静的に組み込まれ soft-segment-descriptor 構制本 ます。 env " MYKERNEL . env " struct soft—segment—descriptor { base unsigned unsigned unsigned ssd—p: 1 unsigned unsigned unsigned ssd—def32: 1 ssd unsigned ssd—type : 5 ssd ssd—gran : 1 ssd xx1:2 —dpl : 2 ファイル MYKERNEL. env は、カーネル成疋ファイ ルと同じディレクトリに作成してください。このファイル には、変数名と値を次のような書式で 1 行に 1 つ記述し kern . 五N="100" ます。 の名前の環境変数を読み込んで大域変数に設定します。 1 , 955 行目で呼び出している init-paraml() は、以下 1301 : 1302 : / * GLDT— SEL LDT デスクリプタ * / {(int) ldt, sizeof(ldt)—l, 0X2 , 3 , 1 , 0 , 0 , 0 , 0 } , ern. hZ ern. maxswzone ern. maxbcache ern. maxtsiz ・ kern. dfldsiz ・ kern. maxdsiz ・ kern. dflssiz ・ kern. maxssiz ・ kern. sgrowslz 竟変数がない場合は、デフォルトの値を設定します。 GDT の再言聢 次に、ⅲ it386 ( ) は GDT を再設定します。 1254 : struct soft-segment—descriptor 1255 : 1256 : 1264 : 1265 : 1273 : 1274 : 1282 : 1283 : 1291 : 1292 : gdt-segs ロ = { { 0X0 , 0X0 , 0 , / * GCODE_SEL { 0X0 , Oxfffff, / * GDATA_SEL { 0X0 , Oxfffff , / * GPRIV_SEL { 0X0 , Oxfffff , 0 , 0 , 1 , 1 } , カーネル用データセグメント * / 0 , 0 , 1 , 1 } , カーネル用コードセグメント * / 0 , の , 0X13 , 0 , 1 , 0x1b , 0 , 1 , 0 , 0 , 0 , 0 , / * GPROCO_SEL swapper 用 TSS デスクリプタ * / 0X13 , 0 , 1 , 0 , 0 , 1 , 1 } , CPU 用データセグメント * / 0X9 , 0 , 1 , 0 , 0 , 0 , 0 } , { 0X0 , sizeof (struct i386tss)—1 , UN 工 X MAGAZINE 2004.4 1 , 254 ~ 1 , 391 行目の配列 gdt-segs は、 GDT デスク リプタの元データを定義しています。ⅲ it386 ( ) は、いく っかのデスクリプタのべースアドレスとリミット値を環境 に合わせて設定します。ところが、実際のデスクリプタ は図 4 のような配置になっているため、べースアドレスと リミット値をあとで変更しようとすると、ビットを左へ回 したり右へ回したりと目が回りそうです。そこで、配列 gdt-segs ではデスクリプタの内容を変更しやすいように 図 5 に示す構造体のデータを用意し、 CPU にロードする 直前にビットを並べなおして図 4 の形式のデスクリプタに 変換した GDT を作成します。 実際のコードでは 15 個のデスクリプタを定義していま すが、こではそのうちの 6 つだけに注目します。 1 , 256 行目は GDT の、、お約束 " で、 1 番目には空デス クリプタを設定しなければなりません。 その次の 1 , 264 ~ 1 , 274 行目は、カーネルを実行するた めのコードとデータセグメントです。この 2 つのセグメン トはべースアドレスが 0 から始まり、その大きさは 4GB ( リミット =FFFFFH かっ G=I) です。ユーザープロセ ス用のセグメントについては後述しますが、 FreeBSD カ ーネルでは、図 6 に示すようにカーネルとユーザープロセ 163

7. UNIX MAGAZINE 2004年4月号

UNiXQ 要プログラマーのための テパッカの基礎知識 プログラミング・ツールとしてのデバッガ ・基本的なデバッグ手法 ・テパッガで会得するホインタ プログラムやライプラリの挙動を調べ Pe 活用のヒント 日本語処理に役立つ知識と関数 リ N ー X ℃ 00000i00 00 N0te 、、 / ツをラを 0 , ・当 ebDAV によるバージョン管理 プログラミング、テクニック 0 ub ′の関ー 6 の実装 ホーム・エ「ランの処 、ヨ P ル—ティング、 い基礎的なル—テイイグ、プロトコル R 旧 , ee 日 SD のプートプロセスをみる 藝 ni 博 86 = CP リデ ? 構造の初期化

8. UNIX MAGAZINE 2004年4月号

特集 デバッガの基礎知識 図 22 メモリ内容Øi 忍 ( 1 ) (gdb) x / 12 &p 確保された領域 変数 buf として 確保された領域 変数 p として (gdb) 0xbfffe6dc : 0xbfffe6cc : 0xbfffe6bc : 図 23 メモリ上に呆された令或 ( 2 ) 0X42015574 0X080483ae : 0X42130a14 ! 0X42130a14 0X00000001 アドレス 0xbfffe6bc 0X4000C6 お 0 三 0X40015360 0xbfffe724 0xbfffe6d8 0xbfffe6f8 0xbfffe72c 意味のない値 0xbfffe6c0 意味のない値 46 ( 省略形は n) コマンドを使います。どちらもプログラムを 実行する ( ステッフ。実行 ) には step ( 省略形は s) や next 定するところまで実行してみます。プログラムを 1 行すっ もうすこしプログラムを進めて、変数 buf に文字列を設 は末はありません ( 図 23 ) 。 こでみているメモリ内容の値に 確保されただけなので、 域です。この時点では、まだローカルな変数として場所が 域、破線で囲った部分カ畯数 buf として確保されている領 図の実線で囲った部分か変数 p として確保されている領 入力しにくいのでこの例では変数名を利用しています。 のようにアドレスの直を直接指定することもできますが、 x コマンドのアドレスを指定する引数には、 0xbfffe6bc う ( 図 22 ) 。 示できればよいのですから、適当に 12 回としてみましょ 数えてももちろんかまいませんが、大雑把にこの範囲カ畩 5 バイト ( buf のサイズ ) ) までにします。回数はちゃんと e6bc から Oxbfffe6c4 (buf の先頭アドレス 0xbfffe6c0 十 1 行すっ実行していくコマンドですが、ほかの関数を呼び 出しているときの動作が異なります。ソースコードが手許 にあるほかの関数を呼び出している場合、 step コマンドで は、その関数の内部に実行が移動します。一方、 next コ マンドでは、その関数は実行されますが内部では実行は停 止せず、関数を呼び出している関数の次の行で止まります。 ほかの関数を呼び出している場合も、ソースコードのない 関数 ( システムのライプラリ関数など ) の場合は、 step コ マンドを使っても関数内部で実行は停止しません。 図 13 の sample3. c では、ソースコードがある関数の 呼出しはおこなわれていないので、どちらのコマンドを使 っても動作は同じです。ここでは step コマンドを実行し、 sprintf 文の行 ( 8 行目 ) が実行されたところまで進みます。 (gdb) s 9 (gdb) p = buf ; sprintf の行が実行されたので、 buf の領域には、、 ABC" という文字列が格納されているはずです。さきほどと同じ ようにして、メモリの内容を確認してみましよう ( 図 24 ) 。 同じく破線で囲った部分が buf の内容です。 char 型の 配列の値なので、デフォルトのワード ( 4 バイト ) 単位で表 示させると見づらいですね。そこで、今度はバイト単位で 表示してみます ( 図 25 ) 。それには、メモリサイズの単位 として b を使います。ここでは buf の内容力寉認でき ればよいので、指定するアドレスも buf の先頭アドレスに します。 さきほどと同じく、破線で囲った部分が buf の内容です。 今度は、見やすくなったのではないでしようか。文字列が 代入される前と比較すると、、、 0X41 0X42 0X43 0X00 " と いう値が入っているのカ寉認できます。文字列、、 ABC" を 数値で表すと、、 0X41 0X42 0X43 0X00 " となるので、メ モリの値もこのようになります。最後の 0X60 という値は buf[4] に相当するメモリの内容ですが、 buf[4] には何も 代入されなかったため、もともとのメモリの値カそのまま UNIX MAGAZ 工 NE 2004.4

9. UNIX MAGAZINE 2004年4月号

デバッガの基礎知識 図 19 ブレークポイントの一キ酳畭 (gdb) b 9 Breakpoint 3 at 0X8048381 : (gdb) b 6 Breakpoint 4 at 0X8048368 : file samp1e3. c, file samp1e3. c, 特集 1 ine 9 . line 6 . (gdb) info break Num Type 3 breakpoint 4 breakpoint (gdb) d Disp Enb Address What keep y 0X08048381 in main at samp1e3. c : 9 keep y 0X08048368 in main at samp1e3. c : 6 De1ete a11 breakpoints? (y or n) y (gdb) info break NO breakpoints or watchpoints . (gdb) 図 20 main 謚にブレークポイントを言綻 (gdb) b main Breakpoint 5 at 0X8048368 : file samp1e3. c, line 8. (gdb) info break Num Type 5 breakpoint (gdb) Disp Enb Address What keep y 0X08048368 in main at samp1e3. c : 8 す。ここで、、 y " を入力すれば、最初からプログラムが実行 されます。 すると、最初のプレークポイントで実行が中断されます。 この段階では、まだ変数 buf と p か亘言されているだけで す。そこで、これらの変数がメモリ上のどの領域に確保さ れたのかを調べてみます。 print コマンドに buf や p という変数をそのまま指定す ると、その変数の内容が表示されてしまいます。ここで表 示したいのはアドレスですから、 print コマンドに変数の アドレスを指定します。 (gdb) p &buf [ 0 ] $ 1 = 0xbfffe6c0 " \ 024 \ n \ 023B ( (gdb) p &p (char * * ) Oxbfffe6bc (gdb) 変数 buf はメモリ上の Oxbfffe6c0 というアドレスから 始まる領域に、変数 p は同じく 0xbfffe6bc に確保されて いることカ認できます ( 図 21 ) 。 それでは、メモリ上のこのアドレスにどのような値が入 っているのかを調べてみましよう。ある範囲のメモリの値 を表示するには x コマンド (examine の意味 ) を使いま す。 実行するときは、 x の後ろに、、 / " ( スラッシュ ) を入力 し、それに続けて表示するアドレスの個数や表示する値の フォーマットなどを指定することができます。何も指定し UN 工 X MAGAZINE 2004.4 図 21 メモリ上にる呆された或 ( 1 ) ない場合は、 ・回数 : 1 ・フォーマット : x ( 16 進数 ) 変数 p として 確保された領域 変数 buf として 確保された領域 アドレス 0xbfffe6bc 0xbfffe6c0 ・メモリサイズの単位 : w ( ワード 4 バイト ) となります。 こでは表示させるアドレスの範囲を、 p の領域 0xbfff 45

10. UNIX MAGAZINE 2004年4月号

連載 FreeBSD の フートプロセスをみる 白崎博生 init386 前回は、 btext による以下の処理について解説しました。 ・ b00t ⅲ fO 構造イ本のコピー ・ CPU の種類の判断 ・ページテープルの作成 ・ページングの肩効化 今回は、 btext の後半で呼び出される init386() に つし ) て説明します。 ⅲ it386 ( ) 1934 : ⅲ it386 ( ) は、 btext からアーキテクチャに依存しない 部分の mi-startup() にジャンプする前に、 CPU 自体お 1940 : よび CPU に依存するデータ構造の初期化をおこないます。 具体的には以下の処理を実行します。 ・ GDT と IDT の再設疋 ・ LDT と TSS の設疋 ・プロセス 0 (swapper) を管理する構造体の初期化 ⅲ it386 ( ) は、ファイル i386/i386/machdep. c て疋義 されています。 プロセスとスレッド構本の初期言聢 1249 : extern StrUCt user *procOuarea; 1250 : extern vm—offset—t procOkstack ; 1918 : void init386(first) 1919 : 1920 : int first; 1921 : { 1930 : 1931 : 1932 : 1933 : 図 1 カーネル用スタック令戓 (procOkstack) struct pcb 608 バイト 16 バイト 8 , 192 バイト スタックの 伸びる方向 ↓ 00000 、 00 atdevbase = 0XC00a0000 ; proc—1inkup(&procO, &ksegrpO, &kseO, &threadO) ; 1 249 ~ 1 , 250 行目の proc0uarea と proc()kstack は、 前回の create-pagetables() で割り当てたデータ領域を指 すポインタで、プロセス情報の一部 (user 構造体 ) やカー ネルスタック、 PCB (Process Control Block) 構造体を 本い図 1 ) するために使用されます。 ⅲ it386 ( ) は、最初にプロセス 0 (swapper とも呼ば れます ) とその実行要素であるスレッドの状態を管理す るデータ構造体を初期化します。 1 , 930 ~ 1 , 940 行目で参 照している変数 proc() と thread() 、 ksegrp() 、 kse() は kern/init-main. c で以下のように定義されます (swap- per は終了しないので、静的に領域を割り当てます ) 。 struct proc procO; struct thread thread0 ; struct kse kse0; struct ksegrp ksegrpO ; 1 , 940 行目の proc 」 inkup() は、プロセスとスレッドを 管理する 4 つの構造体の内容を初期化し、それぞれのあい procO. p—uarea = proc0uarea ; threadO. td—kstack = procOkstack; threadO. td—pcb = (struct pcb * ) (threadO. td—kstack + 2*PAGE-SIZE) ー 1 ; 161 UNIX MAGAZINE 2004.4