雑種路線でいこう

ぼちぼち再開しようか

そうだカーネルを学ぼう

彼は何のカーネルを学んだのだろうか。*1最近の実用OSのソースコードってLinuxにせよWindowsにせよ、SMP対応のチューニングとか電源管理のために核の部分まで非常に複雑になってしまい、読んだりコードを追って動きを理解するのは難儀ではないか。Minixなら教育を意識して平易に実装されているしドキュメントも充実しているから読みやすいし、"Lions’ Commentary on UNIX (Ascii books)"に至っては昔はこんなにシンプルだったかと衝撃を受けるのだが。PDP-11のアセンブラなんて勉強したことないよとか、げ、これGOTO文とか細かいことを気にしてはいけない。Alan Kayが2万行でネットワークからGUIまで含んだ見通しのよい教育用OSを手掛けているらしいので楽しみにしている。とはいえ実務で触るのは複雑なOSなのだから早いうちから複雑なコードに見慣れておくこと自体が教育なのだという考え方もある。コンピュータ・アーキテクチャの全体像を押さえておきたいだけならばMinixでいいけれども、デバイスドライバ等のカーネルプログラミングを手掛けたければLinuxWindows Research Kernel等で腰を据えて学んだ方がいいだろう。
カーネルって意外と汎用性のある知識ではある。特に最近の手に入りやすいOSってLinuxBSDMacintoshWindowsも平準化してきて、ひとつ覚えれば何割かの概念は使い回せるようになった。技術史家としては平準化の背後にある構造に関心を抱きつつ、歴史的にはもっと多様な可能性が試みられたことに言及した上で、次の10年が組込系まで含めてMachライクになっているのか、意外とまたカンブリア大爆発っぽい展開も考えられるのか興味がある。

僕はカーネル技術を学ぶ価値に関して強調せずにはいられない。(略)そう感じるのは、僕がカーネルを学んだからである。
一般的に人は、既に学んだ事の価値は高く、まだ学んでいない事の価値は低く認識する物だ。だから、世の中は常に”既に学んだ者”によって必要性が強調される。しかし、それらが真に価値ある事かどうかは別の問題である。

我々がNSFからの資金を受けてこれからやろうとしているのは、2万行でOS、グラフィックスシステム、ネットワークシステムからエンドユーザーシステムまですべてを書いたようなシステムを作ることである。

OSに於ける技術の平準化についてもうちょっと詳しく説明すると、例えばスケジューリングを例に取ると、10年くらい前だとWindows 9xは過去を引きずった不思議なつくりで、NT系や商用UNIXは真面目にスレッド指向に作り込んでおり、LinuxBSDUNIX古式ゆかしいプロセス指向で、Macintoshはノンプリエンプティブに動いていたが、この10年でどれもすっかりMachライクなスレッド指向に落ち着いてしまった。
プロセスやスレッド周りのデータ構造をみると『インサイド MS WINDOWS 第4版 上 (マイクロソフト公式解説書)』を読んでも『BSDカーネルの設計と実装―FreeBSD詳解』を読んでも、細かい語彙とか実装の違いはあっても概念的には似たようなことが書かれている。結局この10年はSMPでの性能をどう上げるかが重要で、マイクロカーネルは重いから却下だけどMachっぽいデータ構造はイタダキ!って選択が現実的だったのか。にしてもFreeBSDがSMPngでスレッド指向に転向した時は驚いた。同僚のカーネル開発者と話しても「ソース読みにくくなるしメンテも大変だからジャイアントロックでいいじゃん」みたいな意見が主流だったし。
というのも僕は下手の横好きでOSフリークなところがあって、学生時代はUNIXのあとにAT&Tのベル研で開発されたPlan 9やInfernoも触っていたし、岩谷宏の連載記事に唆されてInside AS/400を読んだし、Java OSには興味があったけれども触る機会がなくて、Aperiosって面白そうだけど触る機会がなくてOpen-RってAperiosのAPIなのか違うのか、うーん、みたいな。
前に少し書いたがメモリ保護なんかも20年くらい前はMulticsの影響を受けたi386の4階層のメモリ保護とか、AdaやLISP向けにタグによるメモリ保護をサポートしたiAPX432やi960MXもある。現代でもローエンドの組込系は仮想記憶を使わないし、汎用機の仮想化での効率性を意識したメモリモデルとかSystem iの単一記憶も大きく異なる。この辺はなかなか資料が限られていたのだが、最近はWikipediaが驚くほど細かくフォローしていて読み始めると止まらない。
ところで平準化の理由はPCの普及と入手できる情報やソフトウェア資産の豊富さにあると考えられる。Altoの時代ならOSに手をつける前にプロセッサや言語からつくり始めていたが、ここ20年弱はPCが最も現実的なターゲットだった。*2LinusLinuxの原型となるモニタをつくったのはi386の仮想記憶の使い方を勉強することが目的のひとつだったから、4階層のメモリ保護を駆使する努力をしても不思議ではない。ただ彼がOSを勉強するために参考としたのはPOSIX仕様書だった。Multicsについての情報は限られていたし、もともとLinusMinixユーザーだし、UNIXであればこそGNUの豊富なユーティリティを利用できたから、UNIX互換OSとして2階層のメモリモデルを採用することは自然だったのだろう。KISSの観点でも移植性を考えても、2階層で済めば2階層に越したことはない。
WindowsもNTカーネルは当初から移植性を考えてi860向けに設計されて後にi386/486に移植された経緯があり、i386のセグメントモデルや4階層のメモリ保護に依存することは考え難かった。当時はまだx86命令セットがここまで長寿命化することは想定し難かった。Intelでさえi860やi960でリスクヘッジしていたし、これらが頓挫した後はIteniumに投資した。MicrosoftはACEイニシアチブでPCアーキテクチャx86からMIPS R4000に置き換えようとしていた時期がある。CISC/RISC論争もあり、いずれx86は近代的なRISCアーキテクチャに置き換えられると期待されていた。x86アーキテクチャの延命は、AMDに買収されたNexgenのRISC86や、Pentium ProのμOPSなど、x86の命令セットをサポートしたままRISCの高速化手法を駆使できるようになったことが大きい。また、トランジスタバジェットが増えた割にメモリアクセスの帯域幅が追いつかなかったことがx86RISCの性能差を縮小したことは「x86 以外のプロセッサになにが起こったのか?」が指摘している。
という訳でここ30年近くUNIX技術者が非常に幸せだったとすれば、それは昔取った杵柄がかなり生きたことではないか。C言語K&RからANSIになったとはいえ大きな違いはないし、OSの構成技術もだいたい同じ。シグマプロジェクトに巻き込まれて若い頃にUNIX System 3の自社システムへの移植を手掛けた上司と、浪人時代に親の目を盗んでLinuxFreeBSDを触った僕とが同じ言葉で会話ができるってすごいことだ。対する上位層はこの30年ですっかり一変した。30年前というとGUIライブラリはXerox PARCにしかなかっただろう。10年前のWebプログラミングはPerl/CGIが主流で、PHPも最初はPHP/FIというPerlのライブラリだった。Javaはサーバープログラミングではなくアプレットを書くための道具だった。20年前のWindowsといえば、やっと窓が重なるようになったのが売りだった。
銀の弾丸と喧伝されるような開発生産性を高める道具はいろいろあるが、オブジェクト指向のように生き残ったものもあれば4GLのように忘れ去られたものもある。LISPPrologは面白いけれども80年代に期待されたほどには流行らなかった。そういう意味でもカーネルとかデータ構造、トランザクション管理といった基礎技術を学んだ技術者は、RPGや4GLのような抽象度の高い技術を触った技術者より報われた確率が高いのではないか。一般論として低レイヤの技術の方がゆっくりと時間が流れるし、少しずつ変わっていくにしても追っかける基礎体力を育むことができる。
これは必ずしも流行りものに飛びつく価値がないという訳ではない。例えば新しい技術を学ぶとき、実は技術そのものだけではなくて、情報収集の方法やコミュニティでの振る舞い、技術そのものの進歩や周囲の毀誉褒貶の変遷をも学ぶことができる。運悪く選んだ技術が儚く廃れたとしても、素早く技術を学ぶ方法や、そこから結果を出す方法、技術情報やトラブルシューティングのヒントに網を張るといったメタ技術は使い回しが効く。この技術は廃れるかも知れないと割り切って、新しい技術に飛びつき続けることも戦略としてはあり得る。とはいえ自分が息の長い確立した基礎技術を学んでいるのか、それとも勢いのある応用技術を学んでいるか自覚していることは重要だ。
OSを学ぶことにリスクがあるとすれば、そろそろ転換期に近づいている可能性があることだ。この30年OSの劇的な変化を阻んできた制約条件が崩れつつあるのである。80年代以降もOS技術の研究に進捗がなかった訳ではない。LISPマシンやマイクロカーネル、プロセス移送、単一記憶など、優れた概念であるにも関わらず普及しなかった技術は山ほどある。それは技術情報や既存のアプリケーション資産との互換性、廉価で入手できるマイクロプロセッサのサポートしている命令セット、最適化技術の蓄積など、様々な外部効果を考えると経済的に割に合わなかったのである。特に大きいのは既存のアプリケーションとの互換性である。
この制約条件は仮想化によって解消しつつある。サーバーではサービス毎に仮想機械を分けてリスクを分散できるようになった。クライアントでもIO仮想化やGPU仮想化によって、アプリケーション毎に仮想機械を分けられるようになる。アプリケーション毎に仮想機械を切り替えられるということは、それぞれ異なるOSを実行できるということだ。つまり後方互換性のために古いコードやアーキテクチャを残しておく必要がなくなるのである。
C言語で書かれたコードから脆弱性を根絶することは極めて難しい。2階層のメモリ保護でRootkit等の対策を行う方法も確立されていない。移行コストが低下しているだけでなく、維持コストも高まっており、仮想機械で古いOSを動かすことで後方互換性を保ちながら、仮想化を前提に安全な言語で書かれた全く新しいOSが受け入れられる素地が整いつつあるのである。従来であれば互換性やアプリケーション資産の不備で見向きもされなかったであろう革新的技術が、これから話題になる機会が増えるのではないか。
無論どんな新技術も既存技術の延長線上にあるのだから、転換期がくるからといって学習が無駄になるとは限らない。けれどもこれまでUNIX技術者が享受してきた30年近くの持続的技術革新を、これからのカーネル学習者が享受できるとは限らない覚悟は持った方がいい。ぜひ重要な転換期に立ち会う貴重な機会があるかも知れないと前向きに受け止めて欲しい。そうだカーネルを学ぼう、と。

*1:よくプロフィールを読むと、どう考えてもLinuxですね。失礼いたしました。

*2:それ以前はPCはプロセッサ性能やメモリ容量など近代的なOSを載せるには貧弱すぎたから、研究者たちはワークステーションを使っていた