C言語とUnixの起源

新人研修用C言語の資料

C言語の起源はUnixの起源に重なる。C言語Unixを記述するためのものである。元々はプライベートなツールだった。

Multics〜GE-600のシステム

GEとベル研の共同プロジェクトでGEがIBMから脱却し自社でメインフレームを持つという動機により計画された。
以下Wikipediaより

当初はGE-645用に開発(36ビットシステム)精巧なアドレッシングモードを持ち、様々な間接アクセスが可能で、自動インクリメントや自動デクリメントも備えていた。バイトのサイズはアドレッシングモードの一部として6ビットと9 ビットをサポートしている。特定のバイトを取り出して、バイトポインタをインクリメントするといったことが可能だったが、任意のバイトにアクセスすることはできない。

目新しいところを挙げると

  • シングルレベルストア(思いっきり端折っていうとすべてファイルっつーこと)
  • 動的リンク
  • マルチCPU
  • タイムシェアリング
  • セキュリティ
  • 階層型ファイルシステム
  • 高級言語PL/Iにて記述

Multicsは斬新なアイディアを取り入れたシステムでそれは当時のハードウェアの性能で実現するのはハードルが高かったといえる。1960年代にこんな機能を実装しようとした技術的野心は尊敬に値する。しかしこれはソフトウェア開発の困難さが見えないゆえの蛮勇だったのかも知れない。Multics後にハードウェアの性能が向上したことにより一定の成果を挙げた。ハネウェルのMulticsの血脈は現在のACOS(NEC,東芝)へと受け継がれている。

UNIXの誕生

ベル研のケントンプソンはspaceTravelというゲームをGE-645で開発していたがこれをPDP-7上で実現するためにMulticsの主要なアイディアは受け継ぎ、できる限り小さなシステムを再構築した。つまりゲームをするため以外の機能は大胆にそぎ落とした。これはアセンブラで実装された。
UNIXは野心的なMulticsに対して現実解を与えて成功した、というように語られることが多いがケントンプソンはゲームが出来ればよかったので重厚なシステムは不要だったというのが本当なのではないか。ただしハッカーであるので充実した開発環境は望んでいただろう。いずれにしてもUNIXの前にはMulticsが歩き慣らした道があったのだと思う。

B言語

UNIX上でさまざまなプログラムをするために高級言語が必要であると実感したケントンプソンはBCPLに習ったBという言語を開発する。コンパイルして中間コードに変換されインタプリタで実行されるものであった。ただし後にPDP-7のネイティブコードを吐くものが開発された。
Cとの対比でいうと型がないことが一番の特徴。

変数はワード単位で扱う。多くの演算子は変数を整数として扱いそれ以外はポインタとして扱う。整数とポインタの区別がないのは現在の感覚では違和感があるかもしれない。これは現在の高級言語では左辺値と右辺値の扱いに通じているように思う。現在のプログラマにとっても左辺値と右辺値の違いは特に意識されていない。代入式の左辺では入れ物の箱として、それ以外の式の中では箱の中身として自然に捉えられている。そう考えると当時のハッカーにとってはアドレスと整数が置き換え可能なのは自然な仕様であったろう。

Cの誕生

Cの開発とCによるUNIXの書き直し、PDP-11への移植が時系列的にどのようになっているかあたった資料ではよくわからない。いずれにしてもUNIXを記述するためにC言語が開発されたのは間違いないようだ。
C言語の誕生だけを追うとデニスリッチーはケントンプソンのB言語を改良し、ネイティブコードを吐くようにすると同時に型を持つようにした。これをNewBとしたのが後にCとなった。
Wikipediaより引用

B言語の型付けのない設計はハネウェルやPDP-7などの多くの古いコンピュータでは意味のあることであったが、PDP-11やより近代的なコンピュータの全てがサポートするキャラクタデータ型にエレガントにアクセスすることが難しかったため、PDP-11上では問題があった。

これは想像だが、PDP-11はワードマシンであったためバイト単位でのアクセスを記述するのが煩雑になったのだろうと思われる。

実際の移植作業

CによるUNIXの書き直しとPDP-11への移植は卵と鶏の関係だがどちらが先かはよくわからない。しかし作業的には以下のように進めたと想像する。

  1. (PDP-7)NewBを開発する。ネイティブコードを吐き型を持つ。これがCとなる。つまりPDP-7のアセンブラでネイティブコードを吐くCコンパイラができる
  2. (PDP-7)1のCでPDP-7のUNIXを書き直す。
  3. (PDP-7)2の環境でさらにCコンパイラをCで書き直す。
  4. (PDP-7)2,3を繰り返しシステムコールとCライブラリを充実させる。
  5. (PDP-7)コンパイラを改造してPDP-11のネイティブコードを吐くようにする。おそらくブートストラップとCコンパイラが使える位のシステムだと思う
  6. (PDP-11)5のバイナリをPDP-11に配置しPDP-7のソースをコンパイルする。ソースの可搬性が活きる
  7. (PDP-11)さらにPDP-11上でUnixの開発とCコンパイラの開発を行なう

自分自身と環境を開発する

Cの開発とUNIXの開発はCの記述性の高さを表している。Cは自分のいる環境と自分を産む機械を自分で作ってしまう。これはビル建築のクレーンと似ている。クレーンは初めに組み立てた後は自分自身のマストを自分で吊り下げて伸びていく。大きなビルになると自分が資材を運んで高くしたビルを足場にして自分がさらに上に資材を運ぶ。リンク先参照。
日本クレーン協会 http://www.cranenet.or.jp/tisiki/kuraimingu.html
Cコンパイラは十分小さいのでをアセンブラで書くのも難しくないだろう。もちろんクロスコンパイルをすれば開発はリッチな環境で可能だ。そして自身と、環境を開発するのに必要にして十分な記述力がある。ほとんどのコンパイラはCで開発されているはずだ。JVMJavaで書かれたり、ruby.exeがrubyで書かれたりするだろうか?現在の開発環境なら不可能ではないだろう。
しかしたとえば、新規のCPUを想定したとき、初めに足場を組むのはCコンパイラだろうと思う。



参考資料
Wikipedia:C言語 http://ja.wikipedia.org/wiki/C%E8%A8%80%E8%AA%9E
Wikipedia:UNIX http://ja.wikipedia.org/wiki/UNIX
Wikipedia:Multics http://ja.wikipedia.org/wiki/Multics
C言語の起源をめぐって http://www.lbm.go.jp/toda/comp/corigin.html