玩式草子─ソフトウェアとたわむれる日々

第84回Linuxの成長過程をふりかえる[その3]

前回に引き続き、今回は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のサイズ変遷
図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.131.1.521.1.93
arch/721280
boot/44
drivers/296840824892
fs/114412801356
ibcs/852
include/8409801500
init/161620
ipc/525268
kernel/220236156
lib/484856
mm/100104132
modules/440
net/588604 712
tools/1212
zBoot/8080
total6208767210260

この結果をソースコード全体に占める各ディレクトリの割合に換算し、扇型グラフに描いたのが図2です。図2では、内側から1.1.13、1.1.52、1.1.93の順になっています。

図2 linux-1.1シリーズのディレクトリ構成
図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.01.3.501.3.100
Documentation/496916
arch/134421804712
drivers/5392726411532
fs/137216162072
include/178828803712
init/162428
ipc/686472
kernel/168168100
lib/566464
mm/132148192
modules/000
net/96411761424
scripts/124268
total113881629225284

この結果も、1.1シリーズと同じスタイルで扇型グラフにしてみます。このグラフでも内側が1.3.0、中央が1.3.50、外側が1.3.100の順です。

図3 linux-1.3シリーズのディレクトリ構成
図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.01.3.501.3.100
alpha/180328364
i386/760732796
m68k/2228
mips/168276280
ppc/252264
sparc/236592780

この結果を見ると、i386のサイズはほぼ横這いなものの、alphaでは倍増、sparcでは3倍強にまでサイズが増えており、これらのCPUへの対応は1.3シリーズ全体に渡って続いていたことがわかります。

1.3シリーズでは対応するCPUの種類が増えると共に、SMP(Symmetric Multi Processing)機能への対応も始まりました。ソースコードを調べると、1.3.40の段階でarch/i386/kernel/以下にsmp.ctrampoline.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でマルチポートのパソコン通信ホストを作るのが流行ってたっけ……」と思い出しました。

また、カーネルに関する各種ドキュメントを集めた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でしたが、実際に商用環境で使おうとするとまた新たな問題に直面することになりました。それらについては回を改めて紹介することにしましょう。

おすすめ記事

記事・ニュース一覧