UNIX v6 on simh
Lions' Commentary on UNIX読書会に参加した。いまだにLions本が大学の教科書として現役だという事実に驚いたが、読書会に集まる我々も五十歩百歩か。何はともあれ、一緒に読んだり教えたりしてくれるメンタがいれば、現代でも楽しめる一冊であることは確か。すでに読書会のメモがいくつか書かれているようだけど、@kotritさんがきっとまとめページを作ってくれるはずなので、期待!
ここでは実際にUNIX v6が動いているところを見て理解の助けにしたいということで、PDP-11シミュレータsimhでUNIX v6を動かす方法について書いてみる。
PDP-11は古いマシンではあるんだけど、愛好者が多いのでウェブ上には非常に多くの情報が公開されている。シミュレータの開発や当時のディスクやテープのアーカイブもあるし、ソースコードも公開されている。最初はsimhのSoftware Kitsで公開されているディスクイメージを使ったのだけど、manページやユーザランドのソースコードが含まれていなかったりするので、ドイツの大学で作られたディストリビューションを使うことにした。これはPDP-11のテープアーカイブとして公開されている。ここからダウンロードして、このドキュメントにしたがってインストールしていけばディスクからブート可能なUNIX環境を構築できる*1。ちなみに、simhについてはこの日記でも何度か紹介しており、Mac OS X上でのコンパイル方法はここに書いた。
上記のドキュメント通りに進めれば特に詰まるところもないので、作業自体はあっという間に終わってしまうけど、ディップスイッチを操作してブートローダを手入力したんだなとか、テープからディスクへのコピーにはどれくらい掛かったんだろうと当時を想像しながら、インストールするのも一興。その詳細は追々書いていきたいと思うが、ここでは詳細を割愛する。
さて、simhを起動してみよう。
$ cat unixv6.cfg set cpu 11/40 set tto 7b att rk0 v6root att rk1 v6src att rk2 v6doc ;d sr 1 boot rk0 $ ./pdp11 unixv6.cfg PDP-11 simulator V3.8-1 Disabling XQ @unix login: root #
カーネルのソースコードは今のように構造化されておらず、/usr/sys以下のkenとかdmr(もちんKen ThompsonとDennis Ditchieのこと)というディレクトリに散らばっているのが微笑ましい。
読書会でldivやlremがアセンブリルーチンなのはなぜかって話がでたので、次のコードをコンパイルしてみた。
/ foo(a, b){return a / b;} .globl _foo .text _foo: ~~foo: ~a=4 ~b=6 jsr r5,csv mov 4(r5),r1 sxt r0 div 6(r5),r0 jbr L1 L1:jmp cret .globl .data
一方、カーネルソースのldivはこんな感じ。比較するとプロローグとエピローグにcsvとcretルーチンを呼び出すことのオーバヘッドを嫌ったのかな。また、div命令はdestのr0とr1のペアを32ビット整数とみなして、srcで割るんだけど、下のコードではr0をゼロクリアしているのに対して、上のコードではsxt命令で符号拡張している。今回のケースでは符号拡張する必要はないので、どちらでもいいと思うけど。
1392 .globl _ldiv 1393 _ldiv: 1394 clr r0 1395 mov 2(sp),r1 1396 div 4(sp),r0 1397 rts ps
あと、systm.hでcoremap[CMAPSIZ]とかswapmap[SMAPSIZ]って定義されていてあちこちのソースファイルからインクルードされているけど、多重定義にならないの?という話が出た。nmで見ると、各オブジェクトファイルには_coremapがコモンシンボルとして含まれ、/unixにリンクされた段階で実体は一つになっている。古いCの仕様がよくわからないけど、コンパイル段階ではexternとして扱われ、ローダ(リンカ)で実体を確保し、アドレス解決するのかな。
# nm /unix|grep map 062052B _coremap 062362B _swapmap (一部略)
現在の知識が30年以上前のシステムでもそのまま有効というのは、改めてすごいな。というわけで、Lions本読書のお供にsimhが役に立つかもよという話でした。
余談だけど、ソフトウェアシミュレータじゃ物足りなければ、PDP-11をオークションで競り落とすという方法もあるかもしれない。でも、さすがに普通の家庭に置くことは不可能なので、PDP-11をFPGAで実装したPOP-11を動かすという方法がある。ソースが公開されており、ちゃんとUNIX v6も動くそうだ。ボード自体はALTERAのこの辺のものでいけそうなのかな?
余談その2。manファイルはあるんだけど、manコマンドが見つからない。v7にはmanコマンドあるんだけどな。で、nroffで読んでみようと思ったけど、man用のマクロがないようで整形がいまいち。あとページャがないのがつらい。だれかmanページを適切に読む方法を教えて!
余談その3。/etc以下にinit(カーネルが最初に起動するユーザプロセスは/sbin/initじゃなくて/etc/init)やmount、mknodなどの管理系プログラムがあることに驚いたが、4.3BSDのころに/sbinができるまではこんな感じだったとのこと。
余談その4。sttyで再割り当てできると思うが、デフォルトではeraseが@、killが#に割り当てられている。
*1:chdirを今風にcdでできるようにする変更も何気に便利。