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

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

前回は過去25年間にリリースされたカーネルのサイズと日付を元に、Linuxの成長過程を概観してみました。最後のグラフで紹介したように、過去25年間の間、Linuxのサイズは順調に増大しているものの、その増加ペースは必ずしも一定ではなく、サイズが急増する時期とそうでない時期があるようです。今回から数回に渡って、それぞれの時期にどのような変更が行なわれてきたのかもう少し詳しく見ていくことにします。

前回のグラフはリリースされた日付やサイズが明確になっているlinux-1.0以降を対象にしました。しかし、Linuxの成長過程を考える場合、LinuxがLinuxになった時期を忘れるわけには行きません。そこで、まず最初にLinuxが公式版である1.0に到達するまでの過程を調べてみることにします。

linux-0.01とlinux-1.0

前回も紹介したように、最初に公開されたlinux-0.01は総ファイル数が88、総行数は10239でした。一方、最初の公式版であるlinux-1.0になると、総ファイル数が561、総行数は176250にまで増加しています。

linux-0.01はLinusさんが一人で自分の持っているハードウェアのみを対象に書きあげたバージョン、linux-1.0はその後2年半ほどの間に世界中の開発者から寄せられたコードを取りこんで、80386CPU用のUNIX(POSIX)用カーネルに必要な機能を整えたバージョンです。

両者の間にどれくらいの違いがあるかを見るために、まずはそれぞれのソースコードを展開したディレクトリでリストを取ってみました。

$ ls linux-0.01
Makefile  boot/  fs/  include/  init/  kernel/  lib/  mm/  tools/
$ ls linux-1.0
CHANGES  CREDITS    Makefile  boot/      drivers/  ibcs/     init/  kernel/  makever.sh*  net/    zBoot/
COPYING  Configure  README    config.in  fs/       include/  ipc/   lib/     mm/          tools/

この結果を見ると、linux-0.01ではソースコードはboot、fs、include、init、kernel、lib、mm、toolsの8つのディレクトリに収められているのに対し、linux-1.0ではdrivers、ibcs、ipc、net、zBootという5つのディレクトリが増えて13のディレクトリに収められています。それぞれのディレクトリのサイズをduで調べてみたところ、以下のような結果になりました。なお、duで得られるディレクトリのサイズはファイルシステムの種類によって多少異なることがあり、以下の例はBtrfs上で取った結果です。

linux-0.01linux-1.0
boot/16KB44KB
drivers/2800KB
fs/108KB1100KB
ibcs/8KB
include/4KB780KB
init/4KB16KB
ipc/56KB
kernel/116KB 208KB
lib/48KB64KB
mm/16KB92KB
net/496KB
tools/4KB12KB
zBoot/80KB
464KB5800KB

この結果を見ると、linux-0.01と1.0の間でもっとも差があるのは周辺機器用のドライバを収めたdriversディレクトリでしょう。ソースコードを眺めると、linux-0.01では周辺機器としてキーボードとVT102互換のコンソール、IDE HDDにしか対応していないので、それら用のコードはすべてkernelディレクトリに収められていました。

それに対し、linux-1.0ではdriversディレクトリ以下はFPU-emu、block、char、net、scsi、soundの6つのサブディレクトリに分かれ、HDDやFDDといったデータ記録用のブロックデバイスとコンソールやキーボード、マウスといったキャラクタデバイス、対応しているネットワークカードやSCSIカード、サウンドカード用のドライバがそれぞれのディレクトリに整理された結果、これだけの違いになったようです。

また、ファイルシステム回りのコードも10倍近く増えており、これも内容を見ると、linux-0.01ではMinix用のファイルシステムにしか対応していなかったのに対し、linux-1.0ではMinix FSに加えてLinux専用に開発されたext/ext2 FS、xiafs、相互運用用のmsdos、sysv(SystemV系UNIX用⁠⁠、hpfs(OS/2用⁠⁠、CD-ROM用のisofs、ネットワーク用のNFS、カーネルの内部情報を操作するためのproc FSが追加されています。

もうひとつ、TCP/IPネットワーク機能のコードを収めたnetディレクトリが追加されたのも目を引きます。他の多くのUNIX系OSではBSDが開発したTCP/IP用のコードを流用しているのに対し、Linuxでは0からTCP/IP用のコードを再開発し、linux-1.0の時点ではNET2D(NET2 Debugged)と呼ばれる3世代目のコードが採用されています(NET→NET2→NET2D⁠⁠。

linux-0.01と1.0を比べると、良く言えばプロトタイプ、悪く言えば学生のおもちゃレベルだったカーネルが、まがりなりにもPOSIX互換OSのカーネルとして使えるようになるためには、10倍以上のソースコードが必要だったことが見てとれます。

0.01と1.0の間

linux-0.01が公開されたのが1991年9月、最初の公式版である1.0が公開されたのは1994年3月で、linux-1.0の開発には約2年半かかっています。この間に前節で紹介したようなソースコードのディレクトリ構成が変わる規模の変更が加えられたわけですが、その過程をもう少し詳しく見るために0.01と1.0の間で4つほどのバージョンを調べてみました。対象にしたのは1992年1月に公開されたlinux-0.12、1992年3月に公開された0.95、1993年3月の0.99.5、1994年2月の0.99.15です。

それぞれのバージョンのソースコードに含まれている各ディレクトリのサイズを前節同様の表にまとめてみると以下のようになりました。

linux-0.12(1992/01)linux-0.95(1992/03)linux-0.99.5(1993/03)linux-0.99.15(1994/02)
boot/28KB28KB36KB44KB
drivers/2700KB
fs/128KB152KB585KB1100KB
ibcs/8KB
include/172KB184KB436KB768KB
init/16KB8KB12KB16KB
ipc/56KB
kernel/280KB308KB1200KB208KB
lib/56KB56KB60KB64KB
mm/32KB28KB60KB92KB
net/416KB500KB
tools/8KB8KB16KB12KB
zBoot/80KB
724KB776KB2800KB5700KB

この結果を見ると、linux-0.95とlinux-0.99.5の間、日付けで言うと1992年3月から1993年3月の間の1年間にかなり大きな変更が加えられているようです。

それぞれのディレクトリのサイズで見ると、0.99.5では0.95では対応していなかったTCP/IPネットワーク機能が追加され(netディレクトリ⁠⁠、ファイルシステムもminix FSしか対応していなかった0.95に対して、0.99.5ではLinux用に開発された最初のファイルシステムであるext FSが追加されています。加えてDOS形式のメディアを読み書きするためのmsdos FS、CD-ROM用のisofs、リモートマウント用のNFSが追加され、fsディレクトリのサイズは4倍弱に増加しています。

$ ls linux-0.95/fs
Makefile     buffer.c    exec.c   file_table.c  ioctl.c  namei.c  pipe.c        select.c  super.c
block_dev.c  char_dev.c  fcntl.c  inode.c       minix/   open.c   read_write.c  stat.c
$ ls linux-0.99.5/fs
Makefile     buffer.c  ext/     fifo.c        filesystems.c  ioctl.c  locks.c  msdos/   nfs/    pipe.c  read_write.c  stat.c
block_dev.c  exec.c    fcntl.c  file_table.c  inode.c        isofs/   minix/   namei.c  open.c  proc/   select.c      super.c

また、kernelディレクトリのサイズも4倍近く増加しており、0.95では対応していなかったSCSI HDDに対応し、主要なSCSIアダプタ用のドライバが追加されています。

$ ls linux-0.95/kernel/
Makefile  blk_drv/  exit.c  math/     panic.c   ptrace.c  signal.c  sys_call.s  vsprintf.c
asm.s     chr_drv/  fork.c  mktime.c  printk.c  sched.c   sys.c     traps.c
$ ls linux-0.95/kernel/blk_drv/
Makefile  blk.h  floppy.c  hd.c  ll_rw_blk.c  ramdisk.c

$ ls linux-0.99.5/kernel/
FPU-emu/  blk_drv/  dma.c   fork.c  ioport.c  itimer.c  panic.c   ptrace.c  signal.c  sys_call.S  vsprintf.c
Makefile  chr_drv/  exit.c  info.c  irq.c     mktime.c  printk.c  sched.c   sys.c     traps.c
$ ls linux-0.99.5/kernel/blk_drv/
Makefile  blk.h  floppy.c  genhd.c  hd.c  ll_rw_blk.c  ramdisk.c  scsi/
$ ls linux-0.99.5/kernel/blk_drv/scsi
Makefile   aha1740.c  fdomain.h  scsi.c        scsi_debug.h  sd.c        seagate.c  sr.h        st.h         wd7000.c
aha1542.c  aha1740.h  hosts.c    scsi.h        scsi_ioctl.c  sd.h        seagate.h  sr_ioctl.c  ultrastor.c  wd7000.h
aha1542.h  fdomain.c  hosts.h    scsi_debug.c  scsi_ioctl.h  sd_ioctl.c  sr.c       st.c        ultrastor.hls

キャラクタデバイスに関しても、当時は接続規格が複数あったマウスに対応すると共に、プリンタや仮想コンソール、サウンド機能にも対応しています。

$ ls linux-0.95/kernel/chr_drv/
Makefile  console.c  keyboard.S  pty.c  rs_io.s  serial.c  tty_io.c  tty_ioctl.c
$ ls linux-0.99.5/kernel/chr_drv/
Makefile      busmouse.c  keyboard.c  mem.c    msbusmouse.c  pty.c     sound/    tty_ioctl.c  vt_kern.h
atixlmouse.c  console.c   lp.c        mouse.c  psaux.c       serial.c  tty_io.c  vt.c

もっとも、この段階ではサウンドカード用のドライバ類はカーネルのソースコードとは別配布になっていたようで、kernel/chr_drv/sound/以下にはドライバ用のスタブしかありませんでした。

$ ls linux-0.99.5/kernel/chr_drv/sound/
Makefile  sound_stub.c

これら各種ドライバ類は0.99.5ではkernelディレクトリ中に収められていたものの、0.99.15になると独立したdriversディレクトリにまとめられ、カーネルの機能と周辺機器用ドライバの機能とが区別されるようになります。

linux-0.12から0.99.15までの各バージョンで、カーネルサイズに占める各ディレクトリの割合の変化を扇形グラフにまとめたのが図1です。このグラフを見ると、0.99の世代の中でも周辺機器用ドライバの占める割合が急増しているのがわかります。

最初期のLinuxは「無いよりはあった方がまし」という方針で積極的に周辺機器用のドライバを追加していきました。その結果、対応している周辺機器が多いおかげでより多くの利用者が集まり、より多くの利用者がいるから開発にさらに拍車がかかる、というポジティブ・フィードバック・サイクルが成立しました。これがLinuxが成功した理由のひとつで、その特徴はこのグラフからも読み取れると思います。

図1 カーネルのソースコードで各ディレクトリが占める割合の変化
図1 カーネルのソースコードで各ディレクトリが占める割合の変化

以上の表やグラフから見ると、Linusさんはlinux-0.01公開後の半年間ほど(0.95のころまで)は、Linuxをそれほど高機能化するつもりがなく、⁠自分が使っているPC+αでコンソールが動けば十分」程度に考えていたようです。

しかしLinuxを支持するユーザが増え、彼らからのさまざまなフィードバックが集まってくるに連れ、当初の方針を変更してLinuxをPOSIX互換のきちんとしたカーネルにまで成長させようと決意しました。そして、1年近くかけて世界中の開発者と共にTCP/IPネットワークやSCSI機能、ウィンドウシステムを利用するために必須のマウス用ドライバなどを整備していき、0.99.xの世代でさらに1年かけてそれらを熟成させて最初の公式版である1.0を公開した、そのような歴史がlinux-1.0以前のソースコードから読み取れそうです。

Minixの作者であるA.Tanenbaum教授とLinusさんの"Linux is obsolete"な議論が行われたのがlinux-0.95を公開する直前の1992年1月末のことなので、この議論によってLinusさんがLinuxの存在意義を改めて認識し、より本格的なカーネルの開発へ舵を切った、と推測するのもあながち間違いでは無さそうです。

linux-1.0は、このような苦労を経て、PC互換機で動作するフリーなUNIX(POSIX)互換OSのカーネルとして世に出たものの、当時の商用UNIXと比べると見劣りする点や荒削りな点が多々ありました。次回は、そのような点を地道に改善していったlinux-1.xの世代を見てみようと思います。

おすすめ記事

記事・ニュース一覧