• ビジネス
  • IT
  • テクノロジー
  • 医療
  • 建設・不動産
  • TRENDY
  • WOMAN
  • ショッピング
  • 転職
  • ナショジオ
  • 日経電子版
  • 日経BP
  • PR

  • PR

  • PR

  • PR

  • PR

記者の眼

誰も読まないOSのソース・コード

米田 正明=日経Linux 2006/04/07 日経Linux

 まず,結論から言おう。  「エンジニアがOSのソース・コードを読めるようになると,活躍の場が一気に広がる」。そして,「コツさえ分かれば,OSのソース・コードはびっくりするほど簡単に読める」。

 ここでいうOSとは,Linuxのカーネル(OSの“核”となるソフト)のことである。筆者が上の2点を強く感じたのは,つい最近の,ある人物とのやり取りがきっかけだった。

 「カーネルのソースが読めると,たいそう儲かるってことが,分かってしもうたから」。「もうすぐ大学の仕事は定年や,でも定年後の収入の方が多いんとちゃうかな」---。

 筆者の耳に,迫力ある関西弁が突き刺さった。声の主は1949年生まれの57歳。神戸情報大学院大学助教授の赤松徹氏その人である。

 打ち合わせを兼ねた取材の後の会話だったので,メモは取っていない。赤松氏がはっきりとこの通りに発言したかどうかは覚えていないが,筆者の脳裏には,そのような発言として記憶されている。

 普通の取材なら,「なるほどね」と納得するところである。しかしこのときは少し違った。「さぞかし気持ちいいだろうな」と,少しうらやましくさえ感じたのである。

 ご存知の通り,オープンソース・ソフトウエアであるLinuxは,そのソース・コードが公開されている。誰でも“ただ”で,このサイトなどから簡単に入手できる。

 ソースが公開されていると聞くと,プログラマではない筆者などは,国内でも数多くのLinuxプログラマがソースを読んでいて,どこでどういう処理をしているか,ちょっとしたプロならみんな知っているのだろうな,と思ってしまう。

 しかし,赤松氏によると,Linuxにかなり詳しい技術者でも,ソースを深く読んでいる人は「ほとんどおらへん」という。ソースの一部なら読む人は多いようだが,全体像を把握できるまで詳細に読みこなしている人は,ほとんどいないらしい。

 赤松氏は業界に顔が広く,多くのLinux関係者と話す機会があるが,なかなかソースの中身にまで議論が及ぶことは滅多にないという。むしろ,「カーネルの内部を熟知している先生の知識を生かして・・・してほしい」とか,「こういうソフトを作ってほしい」といった依頼話が多い。現在は,大学で生徒にソフトウエア開発技法や情報ネットワーク技術を教えるという立場もあることから,こうした依頼話の多くは断っているという。しかし,大学の籍が外れたら断る必要はない。「定年後にはバラ色の生活が待っとる」とまで言わんするその57歳の目が,筆者には20代くらいの若者に見えた。

 赤松氏が「ソースを読んでいる人がほとんどいない」と感じる理由はもう1つある。それは,誰もがよく使うソフトでさえバグが大量にある,ということだ。少しでもソースをのぞけば,誰にでもすぐに見つけられるほど簡単なバグなのに,ネットにも情報が上がらず放置されているという。例えば,赤松氏が見つけたバグの具体例を一つだけお見せしよう。

 ネットワーク関連のコマンドの1つに「traceroute」がある。Linuxのコマンド・プロンプトで,「traceroute 宛先のIPアドレス」と打てば,そこに至るまでに経由するルーターのIPアドレスのリストを表示する。これは,厳密にはカーネルのプログラムではないが,通常はカーネルに一緒に添付されている基本的なユーティリティ・プログラムである。Linuxカーネルのバージョン2.6では,IPv6関連のユーティリティが組み込まれており,以下は,その中のtraeroute6コマンドのソース・ファイル「traceroute6.c」の中の705行目から711行目および,718行目から721行目の記述である(2006年2月時点)。

705 static char *ttab2[] = {
706     "Echo Reply",
707     "Echo Request",
708     "Membership Query",
709     "Membership Report",
710     "Membership Reduction",
711 };

718 if (t >= 128 && t <= 132) 719 { 720 return(ttab2[t]); 721 }

 tracerouteは,「ICMP」と呼ぶ,エラー情報などの制御情報をメッセージとして通知するプロトコルを用いる仕組みになっている。ICMPは,メッセージの種類に応じて,異なる「タイプ番号」を割り当てており,メッセージの文字列とタイプ番号の対応を定義したのが705-711行目の記述,その文字列を取り出す処理を記述したのが718-721行目である。

 実は,ここだけで2カ所もバグがある。1つは706行と707行のメッセージが逆であるということ。これは大した誤りではないが,問題は720行目。詳しい説明は省くが,これは配列ttab2の中のt番目のエントリを返すという意味で,tの値が128のときに,ttab2[0],つまり"Echo Reply"を返そうとしているコードだ。が,しかし,ttab2[t-128]とすべきところをttab2[t]とする,極めて初歩的なミスを犯している。配列の範囲を超えて書き込むため,極めて危険なバグである。

 こうしたバグはカーネルのいたるところに存在するため,少し読めばすぐに発見できるそうだ。だが実際にはほとんどは放置されているという。「え,こんなに分かりやすいバグも放置されてるんですか?」。「そう,それだけソースを読む人が少ない,ってことなんや」。

ソースが分かれば危険性も発見できる

 赤松氏によると,カーネルの中核部分やネットワーク処理部分などは,ほぼすべてのソースが頭に入っている。だから,ちょっとしたエラーが起きても,「あ,それは,どこどこの何行目のところでひっかかっとるな」というように,すぐさま頭の中にエラー処理の原因が浮かぶという。

 自分が作ったプログラムではなく,カーネルの処理で,である。筆者も10年以上前に少しだけプログラマだったことがあるが,エラーが起こったときにソースの位置が分かるというのは,せいぜい自分が作ったプログラムだけである。たとえ,OS側の原因で異常終了しても,よく分からず,ただリセットするだけだ。カーネルを読めば,エラーの原因をすぐに突き止められるだけではなく,前述の通りバグを見つけられるので危険な処理を未然に防止することができる。

 このことから,ソースを知っていることは,SEや組み込み系の技術者にとって大きな武器になる,ということがお分かりいただけるだろう。現時点では,詳細にソースを読んでいる人はほとんどいないので,今から読み始めても決して遅くはないのである。

 とはいうものの,実際にソースを読むのは大変な作業である。カーネルのソースのほんの一部だけなら筆者でも読むことができる。だが,まさに「木を見て森を見ず」の状態で,そこだけ見たところでたいしたメリットはない。いろいろなソフトが互いに関連して,さまざまな場所からさまざまな処理関数を呼び出しているため,ある程度は“森”の構造を理解しなければ,ソースを理解したとはいえないからだ。

 カーネルのソースは,C言語で書かれたものだけでも500万行以上もある。1日100行ずつ読んだとしても,136年かかる計算になる。これをすべて読むのは人間では不可能だ。では,なぜ赤松氏はそこまでスラスラと読めるのか。

 聞くと,意外なまでに“普通の答え”が返ってきた。「カーネルのソースを読むんが生活そのものや」という。通勤中も食事中も,どんな時も常にソース・コードのプリントアウトを持ち歩いているというのだ。それを聞くと,中学生や高校生が受験のために参考書や問題集を持ち歩いている風景を思い出した。「30年前に当時ベンツが買えるほどのお金を貯めて,ミニコンを買うた」というほどの熱意を持っている赤松氏だからこそできる業か。

 だが,赤松氏は「ソースを読むのは簡単や」と強調する。赤松氏が読破したのは,カーネルの基本的な部分とネットワーク関連部分,および仮想ファイルである「/proc」の部分である。全体からすればほんの一部だが,これを理解するだけで「まだ読んでいない部分も難なく読めるようになる」という。「何も知らない高校生でも,半年教えれば,スラスラ読めるようになる」ほどである。

 聞くと,どうやら読み方にはコツがあるらしい。プログラムというと,データを定義しているところと,プロセスを記述しているところに分けられるが,カーネルの全体像は,データ構造を理解することにほかならないという。いろいろなデータ構造体のつながりや構造を幾何学的に理解すれば,気持ちよいくらいに全体像が「サッ」と見えてくるそうな。

 全体像が見えたら気持ち良さそう。筆者はそう思い,少しでもそのコツを紹介できないものかと考え,この4月から赤松氏の寄稿による新連載を日経Linuxで開始した。今後,Linuxやオープンソース関連の仕事に接する機会が多くなると思われるITプロフェッショナルの人たちに読んでもらえたら幸いである。

■変更履歴
tracerouteのソース・コードを紹介した部分に誤りがありました。
  705 static char *ttb2[] = {

  705 static char *ttab2[] = {
に,また「tの値が128のときに,ttab2[1]」を「tの値が128のときに,ttab2[0]」に訂正しました。[2006/04/07 11:29]

あなたにお薦め

連載新着

連載目次を見る

今のおすすめ記事

ITpro SPECIALPR

What’s New!

経営

アプリケーション/DB/ミドルウエア

クラウド

運用管理

設計/開発

クライアント/OA機器

ネットワーク/通信サービス

セキュリティ

もっと見る