前回に引き続き、今回はlinux-2.4とlinux-2.5の成長過程を検討します。
linux-2.4.0は21世紀の最初、2001年1月4日に公開されました。次の開発版であるlinux-2.5.0は、linux-2.4.15から分岐する形で2001年11月23日に公開されています。
前回も触れたように、linux-2.4シリーズは「安定版」という位置づけではあるものの、リリース直前まで新しいCPU用のコードが追加されるなど、開発版的な機能も背負わされていました。その傾向はリリース後も変らず、次の開発版が分岐するlinux-2.4.15までは、後述するcrisやs390xといった新しいCPUやReiserFSのような新しいファイルシステムの機能が追加されています。
もっとも、linux-2.5シリーズが分岐した後も、linux-2.4シリーズは2.5シリーズと並進する形でサイズが増加し続け、サイズ増加が収束するのは2.6シリーズがリリースされた後になります。
linux-2.4シリーズと2.5シリーズ、併せて参考のために2.6シリーズの初期のバージョンについて、カーネルサイズの変遷グラフを描くと図1のようになります。グラフを見ると2.5シリーズと2.6シリーズの間にしばらくの断絶がありますが、この期間は2.6.0-test1からtest11というバージョンがリリースされていました。これらのソースコードも保存されてはいるものの、圧縮形式がtar.gzのみで直接比較できないためグラフからは省いています。
このグラフを見ると、linux-2.4シリーズと2.5シリーズでは、「開発版」と「安定版」という関係が曖昧になり、2.5シリーズで開発された新機能が続々と2.4シリーズにフィードバックされ、2.4シリーズのサイズも増加し続けていったことが見てとれます。
かっての1.x世代のように開発版と安定版を厳密に分けてしまうと、開発版の新機能が安定版で利用できるようになるには、次の安定版のリリースまで待つ必要があります。一方、Linuxがより広く利用されるようになってきた2.x世代では、開発版の新機能を安定版に求める人々も増加し、その結果、このように両バージョンが並進する形になったのでしょう。
このような形になると安定版と開発版を区別する必然性も乏しくなります。それに応じて、次の2.6シリーズでは安定版と開発版を一つのバージョンに収め、2.6.xが開発版、それを引き取った2.6.x.yが安定版、というナンバリング形式に変更したようです。
ディレクトリサイズの変遷
それではlinux-2.4/2.5シリーズでどのような機能が追加されてきたのか、ディレクトリサイズの変化から検討してみることにします。上述のように、linux-2.4/2.5シリーズでは2.4.15までは2.4系で開発が進んでいたので、チェック対象には2.4.0、2.5.0(2.4.15と同じ)、2.5.25、2.5.50、2.5.75の5つのバージョンを選びました。これらのバージョンについてサイズの大きい7つのディレクトリの変化を比較したのが図2です。
図2を見ると、linux-2.4/2.5シリーズでもarchやdriversディレクトリが急速に増大しており、新しいCPUや周辺機器への対応が積極的に続いていたことが見てとれます。
この時期のlinuxがどのようなCPUに対応してきたのかを、archディレクトリのサイズから調べると以下のような結果になりました。表中の数字の単位はKB(キロバイト)です。
| 2.4.0 | 2.5.0 | 2.5.25 | 2.5.50 | 2.5.75 |
alpha | 1229 | 1331 | 1434 | 1434 | 1536 |
arm | 1638 | 2560 | 3072 | 3174 | 3277 |
arm26 | - | - | - | - | 928 |
cris | - | 932 | 992 | 976 | 896 |
h8300 | - | - | - | - | 260 |
i386 | 1434 | 1536 | 1741 | 2253 | 2560 |
ia64 | 2355 | 2560 | 3482 | 3584 | 2970 |
m68k | 4301 | 4301 | 4301 | 4301 | 4198 |
m68knommu | - | - | - | 1012 | 896 |
mips | 1536 | 2662 | 2662 | 2662 | 4301 |
mips64 | 864 | 1434 | 1434 | 1434 | 852 |
parisc | 752 | 740 | 760 | 1741 | 1638 |
ppc | 2765 | 3072 | 4915 | 5018 | 4710 |
ppc64 | - | - | 1843 | 1843 | 1741 |
s390 | 584 | 508 | 512 | 488 | 764 |
s390x | - | 620 | 664 | 640 | - |
sh | 396 | 688 | 712 | 704 | 1229 |
sparc | 1331 | 1331 | 1331 | 1331 | 1331 |
sparc64 | 1741 | 1946 | 2048 | 2048 | 1946 |
um | - | - | - | 1229 | 1536 |
v850 | - | - | - | 400 | 416 |
x86_64 | - | - | 1229 | 1229 | 1126 |
前回も触れたように、linux-2.3シリーズの終了時(2.3.51)と比較すると、2.4.0の時点でpariscとs390のディレクトリが増えています。
その後、2.4.0から2.5.0の間にcrisとs390xというディレクトリが増え、2.5.25の時点でppc64とx86_64、2.5.50の時点でumとv850、m68knommu、2.5.75の時点でarm26とh8300というディレクトリがそれぞれ増えています。
crisはAXIS Communications社が開発していた組み込み向けのCPUで、主にネットワーク機器に使われていたそうです。s390xはIBM S390シリーズの新しい64ビット版ハードウェア用のコードで、2.5.0の時点では独立したディレクトリとしてソースコードにマージされたものの、後にはs390用のコードと統合され、s390ディレクトリへ移されました。
ppc64は64ビット版のPowerPC用、x86_64は最近主流になっている、x86と互換性を持った64ビットCPU用のコードです。
2.5.50の時点で入っているumはUser Mode Linuxと呼ばれるユーザ環境でカーネルを動かすためのコード、v850はNECが開発した組み込み環境向けCPU用のコードです。m68knommuは、MMU(Memory Management Unit)を持たない古い世代のm68k用のコードです。
2.5.75で現われたarm26は古い26ビット版ARM CPU用のコードで、元々はarmディレクトリに収められていたものの、新しい32ビット版のARM CPU用のコードとは共存しづらくなったので分離、独立されたそうです。h8300には日立が開発した組み込み向けCPU、H8/300H用のコードが収められています。
この結果を見ると、linux-2.4/2.5シリーズでも、64ビットCPUやメインフレームのみならず、組み込み環境向けのCPUまで、さまざまな種類のCPUに積極的に対応し続けていたことがわかります。また、x86_64への対応が実機の発売前から始まっていることが示すように、IBMやAMDなどの企業がLinuxの開発に積極的に関わってきたことも見てとれます。
もうひとつ、前回までとは異なり、図2にはsoundというディレクトリが現われています。従来、soundディレクトリはOSS(Open Sound System)用のドライバを収めてdriversディレクトリ以下に配置されていたものの、linux-2.5.25以降ではALSA(Advanced Linux Sound Archtecture)のコードがマージされ、driversディレクトリから独立したディレクトリになりました。
さて、残りの比較的小さなサイズのディレクトリのサイズの変遷をまとめた結果が図3になります。
図3を見ると、2.5シリーズの後半でいくつか新しいディレクトリが作られていることに気づきます。cryptoディレクトリにはAESやBlowfishといった暗号処理用のコードが収められ、securityディレクトリは2.5.75の時点ではまだスタブ用のコードしか入っていないものの、後にLSM(Linux Security Modules)と呼ばれる、さまざまなセキュリテイ機能を提供するためのフレームワーク用のコードが収められています。また、usrディレクトリには起動時に利用するinitrdを展開するためのコードが収められています。
ipcのようにほぼサイズの変わらないディレクトリがある一方、kernelやmmはこの時期全体を通じて増加し続けており、機能強化や新機能の追加が継続して行なわれていたことがわかります。
たとえば、linux-2.4.0/kernel/とlinux-2.5.75/kenel/を比較してみると、以下のような14のファイルが追加されていて、CPUの周波数管理機能が追加されたり、プロセス管理機能が強化されたことがうかがえます。
scriptディレクトリが2.5シリーズの後半で急増しているのは、この時期にカーネルをビルドするためのMakefileが全面的に書き直され、現在に続くKconfigという設定メニューを採用したことによるものです。
ジャーナリング・ファイルシステムの採用
linux-2.4/2.5シリーズの開発で特筆すべきは、ジャーナリング機能に対応したファイルシステムの採用でしょう。
linux-1.0以来利用されてきたext2ファイルシステム(FS)は、シンプルながら柔軟性に富んだファイルシステムとして長く愛用されてきたものの、Linuxがビジネス分野へ進出するにつれ、力不足が感じられてきました。
たとえば、ジャーナリング機能を持たないext2 FSでは、動作中に電源断等のシステムトラブルが起きると、ファイルシステム上のデータとファイルの管理情報に食い違いが生じることがあります。このような食い違いは再起動時に実行するfsckコマンドで調査、復旧できるものの、fsckが動いている間、ファイルシステムはリード・オンリーになるので、他の操作は一切できなくなります。加えて、fsckはファイルシステム全体を調査する必要があるので、HDDが大容量化するにつれ長い時間を要することになります。
このようなダウンタイムはビジネス分野では致命的なため、ext2 FSに替わる新しいファイルシステムが求められるようになりました。
そのようなニーズに応えてまず採用されたのがReiserFSです。ReiserFSはファイルシステム開発の専門家Hans Reiser氏らがLinux用に0から開発したファイルシステムで、二分木(B-tree)のアイデアを用いて高速な処理を実現すると共に、ジャーナリング機能にも対応していました。ReiserFSはlinux-2.4.10のころにカーネルのソースコードにマージされました。
一方、ext2 FSの開発者たちも、ext2 FSにジャーナリング機能を追加したext3 FSを開発し、linux-2.4.15のころにカーネルにマージされました。
ReiserFSやext3 FSがLinux用に新しく設計されたファイルシステムなのに対し、商用UNIX用に開発された、実績のあるファイルシステムを移植しようという動きも起こります。
IBMは自社のAIX用に開発したJFSをLinuxに移植し、そのコードは2.5シリーズの前期(linux-2.5.25以前)にカーネルのソースコードにマージされました。一方、SGIはIRIX用に開発したXFSを移植し、2.5シリーズの中期(linux-2.5.50以前)にマージされました。
この結果linux-2.5シリーズの後半では、ジャーナリング機能を持った新しいファイルシステムとしてReiserFS、ext3 FS、JFS、XFSの4つが選べるようになり、それぞれのファイルシステムが互いに切磋琢磨して、Linuxのファイルシステム機能は急速に進化していくことになりました。
ダウンロードしたソースコードからビルドしたlinux-2.5.75のファイルシステム選択画面は図4のようで、ext3、ReiserFS、JFS、XFSがそれぞれ競いあっている様が見てとれます。
spinlock()の進捗
最後に、前回同様、ソースコード中に現われるspinlock()の数を調べてみましょう。ソースコードのうちspinlock()~ unspinlock()で囲まれた部分は、複数のCPUが動いている環境下で、あるCPUが実行している処理を他のCPUの干渉から保護する機能を持ち、いわばカーネル内部の処理単位と言えます。この処理単位が細かくなればなるほど、すなわちspinlock() ~ unspinlock()の数が増えるほど、カーネル内部の処理は細粒化されることになり、その結果、CPU間のデッドロックが少なくなって、SMP環境での処理能力が高まることが期待されます。
前回同様、findとgrepを組み合わせてソースコード中に現われるspinlock()を数えると、linux-2.4.0で2189、2.5.0で2770、2.5.25で3783、2.5.50で4383、2.5.75で4585となりました。ソースコードを展開した状態でlinux-2.4.0が114MB、linux-2.5.75が200MBなので,ソースコードは約1.8倍に増加したのに対し、spinlock()数は2.1倍まで増加しているので、spinlock()を用いたソースコードの細粒化は着実に進んでいると考えられます。
一方、少し見方を変えて、カーネルのソースコードを構成する全てのファイルのうち、spinlock()というキーワードが現われるファイルがいくつあるかを数えてみたのが以下の表です。例えばlinux-2.4.0の場合、ソースコードを構成する総ファイル数が8187、そのうちの764ファイルにspinlock()という語が現われています。
バージョン | 総ファイル数 | spinlock()が現われる ファイル数 | 割合 |
2.4.0 | 8187 | 764 | 0.093 |
2.5.0 | 9893 | 1062 | 0.107 |
2.5.25 | 11815 | 1453 | 0.123 |
2.5.50 | 13561 | 1715 | 0.126 |
2.5.75 | 15003 | 1812 | 0.121 |
結果を見ると、初期のころはspinlock()が現われるファイルの割合は10%以下だったものの、開発の進展とともに12%程度まで増加していることがわかります。この結果も、spinlock()を使ったカーネルの内部処理の細粒化が進展していることを示しているようです。
もっとも、2.5.50では12.6%まで増加した割合が、2.5.75では12.1%とやや減少していることも気になります。この程度は誤差の範囲なのか、あるいはspinlock()以外のロック方式が普及し始めたことを示すのか、そのあたりは別の機会に考察してみることにしましょう。
ここまで6回に渡って、最初期のlinuxから2.5シリーズまでのソースコードをふりかえってみました。linux-0.01がリリースされたのが1991年、linux-2.5.75がリリースされたのが2003年7月12日なので、ここまでで約12年間分ということになります。今年、2016年で25歳を迎えたLinuxのほぼ前半生というところでしょうか。
次のlinux-2.6シリーズは、本文中でも触れたように、「開発版」と「安定版」という区別が廃され、2.6.x.yの中で開発版と安定版が同時進行する形になりました。その結果、従来のように「開発版で1年前後開発を進めて、次の安定版を公開」というサイクルも無くなり、linux-2.6シリーズは2003年12月のlinux-2.6.0から2011年8月のlinux-2.6.39.4まで、8年弱の間続くことになります。
linux-2.6シリーズはこのように従来のバージョンとは異なる特徴を持っているため、その成長過程を検討するのも今までと同じ方法は使えなさそうです。そのため「Linuxの成長過程をふりかえる」シリーズもこのあたりで一区切りにしようと思います。