前回 に引き続き、今回はlinux-1.x世代の成長過程を検討します。
前回紹介したように、linuxは0.99世代でずいぶん迷走しました。その原因が「新機能の追加 」と「安定化 」という相反する目標を同時に追求した結果だと考えたLinusさんは、1.0以降、「 開発版」と「安定版」を分離して2つの目標をそれぞれ異なるシリーズで追求することにしました。
「開発版」は新機能を積極的に追加していくシリーズで多少不安定になることがあっても構わない開発者向け
「安定版」は過去との互換性を重視したシリーズでバグフィックスを中心とした一般ユーザー向け
このような位置づけで、両者はバージョン番号の2ケタ目(マイナーバージョン)で区別されます。linux-1.x世代で言えば1.0と1.2が安定版、1.1と1.3が開発版です。
開発版では新しい機能やドライバが積極的に取り込まれ、週に数回、新しいバージョンがリリースされます。必要な機能が揃い、十分安定した、と判断されれば、開発版の最終バージョンが次の安定版の最初のバージョンになります。1.x世代の場合、linux-1.1は96回バージョンアップを繰り返して1.2 になり、linux-1.3は114回バージョンアップして、メジャーバージョンを更新した2.0 になりました。第82回 で紹介したカーネルサイズの変遷グラフから、この期間のみを取り出して描いたのが図1 です。
図1 linux-1.xのサイズ変遷
なお、linux-1.0のシリーズも10ほどのバージョンがリリースされているものの、www.kernel.org にはパッチファイルしか保存されていないため、図ではlinux-1.0のみを記しています。また、1.1のシリーズも前半部は飛び飛びにしか保存されていないため、グラフはやや粗くなっています。
図1からわかるように、開発版の両シリーズとも開発期間は約1年で、その期間中に1.1では約1.6倍、1.3では2倍強にまでサイズが増加しています。以下、それぞれのシリーズでどのような機能が追加されたのかを詳しく見てみることにします。
linux-1.1シリーズ
linux-1.1シリーズは1994年4月 に開発が始まり、96回のバージョンアップを経て、1995年3月 に開発終了、最終バージョンが新しい安定版であるlinux-1.2 となりました。
このシリーズの開発経過を調べるために、前期(1.1.13) 、中期(1.1.52) 、後期(1.1.93)の各ソースコードを展開し、トップディレクトリ直下のサブディレクトリのサイズを調べてみました。表中の各数字の単位はKB(キロバイト)です。
1.1.13 1.1.52 1.1.93
arch/ 72 1280
boot/ 44
drivers/ 2968 4082 4892
fs/ 1144 1280 1356
ibcs/ 8 52
include/ 840 980 1500
init/ 16 16 20
ipc/ 52 52 68
kernel/ 220 236 156
lib/ 48 48 56
mm/ 100 104 132
modules/ 4 4 0
net/ 588 604 712
tools/ 12 12
zBoot/ 80 80
total 6208 7672 10260
この結果をソースコード全体に占める各ディレクトリの割合に換算し、扇型グラフに描いたのが図2 です。図2では、内側から1.1.13、1.1.52、1.1.93の順になっています。
図2 linux-1.1シリーズのディレクトリ構成
この表と図で目に付くのは1.1.52から現われているarch ディレクトリです。archディレクトリは1.1.52の段階では72KBほどと小さいものの、1.1.93では1280KBまで増加し、ソースコード全体の1割強 を占めるようになっています。
このディレクトリにはlinuxが対応しているそれぞれのCPU専用のコードが収められています。具体的には、元々サポートしているi386以外に、alpha、mips、sparcの各ディレクトリが追加されています。
$ ls linux-1.1.93/arch/
alpha/ i386/ mips/ sparc/
archディレクトリは1.1.52で作られてはいたものの、その時点ではi386用のコードしか入っていませんでした。
$ ls linux-1.1.52/arch
i386/
どのバージョンでどのarch用のディレクトリが追加されたのかを調べてみたところ、1.1.70でalpha が、1.1.73でsparc が、1.1.83でmips が、それぞれ確認できました。
現在の、上はメインフレームや世界最速のスーパーコンピュータから、下はスマホやRasberry PiのようなワンボードマイコンまでサポートしているLinuxに慣れた目からすると、「 マルチ・アーキテクチャ対応」などあたりまえではないか、と思われるかも知れません。
しかし本連載でも紹介したように、もともとのLinuxは80386CPUを積んだPC互換機のハードウェアを直接操作するために書かれたソフトウェアで、80386以外のCPUのことなど一切考慮していませんでした。
Linuxが手本にしていたUNIXは「高級言語(C)で書かれた最初のOS 」として知られ、異なるハードウェア(CPU)に移植可能なことが大きな特徴でした。そのUNIXを手本にしながら、80386CPUに強く依存した作りになっていた最初期のLinuxは、前回紹介したTanenbaum教授をはじめ、古くからのUNIXユーザの批判の的になりました。Linux-1.0が公開されたころには、BSD UNIXの正当な後継者である386BSD やそれを元にしたNetBSD 、商用のBSD/OS なども公開されており、筆者などもずいぶん肩身の狭い思いをした記憶があります。
Linusさんを中心としたLinuxの開発者も同じ思いをし、linux-1.1シリーズの前半で徹底的な整理と書き直しを行って、汎用的な部分とハードウェアに依存した部分を切り分け、Linuxをマルチ・アーキテクチャに対応できるようにしていきました。その成果を踏まえ、linux-1.1シリーズの後半で、DEC AlphaやMIPS、SPARC用のコードを少しずつソースコードに組み込んでいった、そのような歴史がこれらの表やグラフからも見てとれます。
もうひとつlinux-1.1のシリーズで注目すべき点はmodules ディレクトリでしょう。Linuxはマイクロカーネルの評価が定まった1990年代に、古いモノリシックカーネルの設計で公開されました。この点がOS研究者から批判されたのは前回紹介した通りです。一方、マイクロカーネルはプログラミングが面倒で、性能を出すのも大変、という問題があります。そこでLinuxの開発者たちが採用したのは「ドライバ類をモジュールとして用意し、必要に応じて動的に組み込む」というモジュールカーネル のアイデアです。
従来、コンパイラが出力するオブジェクトファイルは、シンプルなa.out 形式やCOFF (Common Object File Format)形式が使われていました。しかし、これらのファイル形式ではコードやデータをメモリ上のどの位置に配置するか事前に決めておく必要があったため、共有ライブラリのような動的に読み込まれるファイルをうまく扱うことができません。そこで考案されたのがコードやデータをメモリ上の任意の位置に配置できるようにしたELF (Executable Linkable Format)と呼ばれる形式です。
ELF形式を使えば、必要に応じて動作中のソフトウェアにでも新しいコードを追加できる、この機能に注目したLinuxの開発者たちは、まずはネットワークカード用のドライバをモジュール化し、必要に応じて動的に組み込めるようにしました。このために利用されたのがmodulesディレクトリです。
linux-1.1.93のREADME.modulesを見ると、当時モジュールドライバとして利用できたのは、minix, xiafs, msdosといった補助的なファイルシステム(ext2は未対応) 、aha1542などのSCSIアダプタ、3c501、3c509、de600といったネットワークアダプタなど、限られたドライバ類だけでした。しかし、これらのドライバのおかげでモジュール機能の有効性は広く認められるようになり、伝統的なモノリシックカーネルでも、先進的なマイクロカーネルでもない、「 モジュールカーネル」というLinuxの方向性が決まることになりました。
これらを考え合わせるとlinux-1.1のシリーズは、その後のLinuxの方向性を定めたきわめて重要な開発版だった、と言えるでしょう。
linux-1.3シリーズ
linux-1.1シリーズは1995年3月で開発が終了し、新しい安定版カーネルであるlinux-1.2が公開されました。linux-1.3シリーズは、このlinux-1.2を元にした新しい開発版カーネルで、1995年6月 から開発が始まり、114回のバージョンアップを経て、1996年6月 に開発終了、次の安定版カーネルはメジャーバージョン番号を更新したlinux-2.0 になりました。
前節同様、linux-1.3シリーズも初期(1.3.0) 、中期(1.3.50) 、後期(1.3.100)のソースコードを展開し、各ディレクトリのサイズを調べてみました。
1.3.0 1.3.50 1.3.100
Documentation/ 496 916
arch/ 1344 2180 4712
drivers/ 5392 7264 11532
fs/ 1372 1616 2072
include/ 1788 2880 3712
init/ 16 24 28
ipc/ 68 64 72
kernel/ 168 168 100
lib/ 56 64 64
mm/ 132 148 192
modules/ 0 0 0
net/ 964 1176 1424
scripts/ 124 268
total 11388 16292 25284
この結果も、1.1シリーズと同じスタイルで扇型グラフにしてみます。このグラフでも内側が1.3.0、中央が1.3.50、外側が1.3.100の順です。
図3 linux-1.3シリーズのディレクトリ構成
これらの表とグラフを見ると、1.3シリーズではarch 以下のコードが急速に増えていることが分かります。実際のソースコードを眺めてみても、当初は1.1シリーズを引き継ぎ、alphaとi386、mips、sparcの4つのディレクトリだったものの、1.3.50ではPowerPC用のppc ディレクトリが、1.3.94ではMC68000用のm68k ディレクトリが追加されています。
arch以下のサイズをそれぞれのバージョンで調べたところ、以下のような結果になりました。
1.3.0 1.3.50 1.3.100
alpha/ 180 328 364
i386/ 760 732 796
m68k/ 2228
mips/ 168 276 280
ppc/ 252 264
sparc/ 236 592 780
この結果を見ると、i386のサイズはほぼ横這いなものの、alphaでは倍増、sparcでは3倍強にまでサイズが増えており、これらのCPUへの対応は1.3シリーズ全体に渡って続いていたことがわかります。
1.3シリーズでは対応するCPUの種類が増えると共に、SMP (Symmetric Multi Processing)機能への対応も始まりました。ソースコードを調べると、1.3.40の段階でarch/i386/kernel/以下にsmp.c やtrampoline.S といったSMP用のコードが現われています。もっとも、SPARC CPUでマルチプロセッサに対応するためのmp.S というコードは1.3.10の段階でarch/sparc/kernel/に現われているので、SMPへの対応はまずSPARC用が先行し、i386はそれを追う形になったようです。
archディレクトリ以外ではdriver ディレクトリの増加も目に付きます。1.3.0と1.3.100を比べると、特にキャラクタデバイス用のドライバ(char ディレクトリ)が大きくなっており、何が追加されたのだろうとディレクトリを眺めてみたらStallionやCyclades、Riscom8といった懐かしい名前がありました。それらを見ると、「 あぁ、このころはLinuxでマルチポートのパソコン通信ホストを作るのが流行ってたっけ……」と思い出しました。
StallionやCyclades、Riscom8というのは、1台のマシンに複数の電話回線を接続するための「マルチポートシリアルカード」で、これらを使えば「話し中」でパソコン通信のホストに接続できない状態を減らすことができます。
また、カーネルに関する各種ドキュメントを集めたDocumentation ディレクトリが追加されたのも興味深いところです。Linuxの場合、TLDP (The Linux Documentation Project)のようなプロジェクトが立ちあがり、一般ユーザ向けドキュメントの整備は早い時期から進んだものの、開発者向けのドキュメントは「ソースコードを読め!」という状態が長く続いていました。
しかしながら、Linuxの普及が進み、開発に新規参加しようという人々が増えてくると共に、カーネルに関するドキュメントへのニーズが高まり、それらを集めたDocumentationディレクトリも必要になったようです。もしかしたらこの時期から、所属企業に命じられ、業務としてカーネル開発に参加するプログラマが増えてきたのかも知れません。
これらの結果から見ると、linux-1.3シリーズは1.1シリーズで成功したマルチ・アーキテクチャ化をさらに進め、SMPのような複雑な構成まで対応できるようするための開発版だったと言えそうです。また、CycladesやRiscom8といった特定用途向けの高価なカード用のドライバが追加されていることから見て、この時期からLinuxがビジネス分野でも本格的に利用されはじめていたことがわかります。
このような成果に自信を深めたLinusさんを中心とする開発者たちは、「 Linuxは、コンピュータマニア向けのホビー的なカーネルから、ビジネスでも使える本格的なカーネルに生まれ変わった」というメッセージを込めて、次のバージョン番号に2.0 を選んだのでしょう。
さて、こうしてlinux-1.0のリリースから2年強の時間をかけて生まれたlinux-2.0でしたが、実際に商用環境で使おうとするとまた新たな問題に直面することになりました。それらについては回を改めて紹介することにしましょう。