Xv6 (2)
carの検査はどうあるべきか?
そんなの、nilで無いlistが一つ渡って来てる事を確認すれば、いんでねぇ。
違うってば、今回はcarはCARでも、自動車検査登録制度 の話ね。何で急にと言うと、2年に一度(3年目のやつはとっくに過ぎた)の、不可解な奴が 巡ってきたからだ。
最近は車屋に頼まないで、自前でやる人もいるようだけど、どんな検査が行われるの? 調べてみたら、車検の点検項目とか 車検本番とかが出てきました。carと違っていろいろ検査 すんのね。
でも、今の車性能上がってるから、2年に一度なんて無駄じゃねぇ? 役人の天下り先確保と業界 が潤うようになってるんだな。だから、制度の改革とかは俎上に上らないんだな。権益保持が この間当選した議員さんの最大の目的だったりしませんか。 このあたりで、ガツンと黒船が攻めてきて、緩和してちょうだいな。
まあ、文句を言うなら車やめろって言われそうだけど、田舎で車が無かったら、身動き出来んわな。 だから、よぼよぼのおばーちゃんでも、車に乗ってスーパーへ買い物に来るんよ。この間、スーパーで 隣によぼよぼのおばーちゃんが車止めたけど、ぶつけられそうなんで、さっさと逃げ出しましたよ。
FreeBSDでもxv6
前回、FreeBSDではコンパイルに失敗しちゃったんで安易にArchLinuxに逃げちゃったけど、要の Makefileを見てたら、解決方法が示されていた。
# FreeBSD ld wants ``elf_i386_fbsd'' LDFLAGS += -m $(shell $(LD) -V | grep elf_i386_fbsd 2>/dev/null)
リンカーフラグをFreeBSD用にせいとな。どんな風にコンパイルが進んで行くかログを取ってみた。
gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pic -O -nostdinc -I. -c bootmain.c gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pic -nostdinc -I. -c bootasm.S ld -m elf_i386_fbsd -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o objdump -S bootblock.o > bootblock.asm objcopy -S -O binary -j .text bootblock.o bootblock ./sign.pl bootblock boot block is 503 bytes (max 510)
アセンブラとCで書かれたファイルをコンパイルして、スタート番地を0x7c00にしたbootblockってのを 作っているんか。学習用に逆アセンブルしたファイルも作ってるんだな。 そして、最後にパアルさんにお願いして、サイズをチェックしてるんか。1セクターに収まって よかったね。
FreeBSDからは、このブートブロックがどのように認識されてるかな? 一応見とく。
[sakae@secd ~/xv6]$ file bootblock bootblock: x86 boot sector; partition 3: ID=0x83, starthead 252, startsector 4291262430, 16783381 sectors; partition 4: ID=0x5b, starthead 131, startsector 195, 0 sectors, code offset 0x31
ブートブロックの証拠は、最後のワードが "aa55" になってる事で確認出来たよ。上で出てきた パアルさんの本当の目的は、この刻印を押す事だった。ついでなんで、FreeBSDの /bootの中には ブートブロックとおぼしきものが幾つも入っているので、ちょいと覗いてみる。
[sakae@secd /boot]$ file mbr mbr: x86 boot sector, code offset 0x31 [sakae@secd /boot]$ file boot1 boot1: x86 boot sector; partition 4: ID=0xa5, active, starthead 0, startsector 0, 50000 sectors, code offset 0x3c
それにしても、スタート番地が変なアドレスだな。これは歴史的な由縁によるものだそうです。 0x7C00の謎を参照。
おっと、リンカーに -mで渡される値は何よ? info ldすると出てた。
`-m EMULATION' Emulate the EMULATION linker. You can list the available emulations with the `--verbose' or `-V' options. If the `-m' option is not used, the emulation is taken from the `LDEMULATION' environment variable, if that is defined. Otherwise, the default emulation depends upon how the linker was configured.
リンカーがいろいろな環境用(対面するOS側のローダーの都合に合せて)に態度を変えてくれるって事? FreeBSDではどんな環境に対応してんのかな?
[sakae@secd ~/xv6]$ ld -V GNU ld (GNU Binutils) 2.22 Supported emulations: elf_i386_fbsd elf_i386 i386bsd
取り合えず、ふーんと肯いておきましょう。そのうちに、リンカーを暴いてやるぞ。 先に進みます。
gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o bio.o bio.c : perl vectors.pl > vectors.S gcc -m32 -gdwarf-2 -Wa,-divide -c -o vectors.o vectors.S gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o vm.o vm.c gcc -m32 -gdwarf-2 -Wa,-divide -c -o entry.o entry.S gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pic -nostdinc -I. -c entryother.S ld -m elf_i386_fbsd -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o objcopy -S -O binary -j .text bootblockother.o entryother objdump -S bootblockother.o > entryother.asm gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -nostdinc -I. -c initcode.S ld -m elf_i386_fbsd -N -e start -Ttext 0 -o initcode.out initcode.o objcopy -S -O binary initcode.out initcode objdump -S initcode.o > initcode.asm ld -m elf_i386_fbsd -T kernel.ld -o kernel entry.o bio.o console.o exec.o file.o fs.o ide.o ioapic.o kalloc.o kbd.o lapic.o log.o main.o mp.o picirq.o pipe.o proc.o spinlock.o string.o swtch.o syscall.o sysfile.o sysproc.o timer.o trapasm.o trap.o uart.o vectors.o vm.o -b binary initcode entryother
これでやっとカーネルが出来上がる。割り込み用のベクター作成はパアル君に頼ってるのね。
gitで取ってきたソースは、フラットにファイルが置いてあるけど、何がどれに関わっているかは、 runoff.list に説明が載ってる。嗚呼、分類されてるのはカーネル関係者だけで、ユーザーランドの やつは、名は体を表すから自分で判断してねって要求なのね。もう、大学生なんだから、それぐらいは 出来るでしょって態度。以下、runoff.listの一部抜粋。
# entering xv6 entry.S entryother.S main.c # user-level initcode.S usys.S init.c sh.c
コンパイルは、続いてユーテリティのmkfsとユーザーランドを用意していく。
gcc -m32 -Werror -Wall -o mkfs mkfs.c gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o ulib.o ulib.c : gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o cat.o cat.c ld -m elf_i386_fbsd -N -e main -Ttext 0 -o _cat cat.o ulib.o usys.o printf.o umalloc.o objdump -S _cat > cat.asm : ./mkfs fs.img README _cat _echo _forktest _grep _init _kill _ln _ls _mkdir _rm _sh _stressfs _usertests _wc _zombie used 29 (bit 1 ninode 26) free 29 log 10 total 1024 balloc: first 429 blocks have been allocated balloc: write bitmap block at sector 28
いろいろなユーザーランドのコマンドを寄せ集めて、ファイルシステムを作り出しているんだな。 そして、最後に、カーネル用のDISKイメージを作り上げるとな。
dd if=/dev/zero of=xv6.img count=10000 10000+0 records in 10000+0 records out 5120000 bytes transferred in 0.112925 secs (45339806 bytes/sec) dd if=bootblock of=xv6.img conv=notrunc 1+0 records in 1+0 records out 512 bytes transferred in 0.000054 secs (9502140 bytes/sec) dd if=kernel of=xv6.img seek=1 conv=notrunc 293+1 records in 293+1 records out 150365 bytes transferred in 0.002381 secs (63149747 bytes/sec)
こうして出来上がったものを起動してみます。
[sakae@secd ~/xv6]$ gmake qemu-nox dd if=/dev/zero of=xv6.img count=10000 dd if=bootblock of=xv6.img conv=notrunc dd if=kernel of=xv6.img seek=1 conv=notrunc qemu -nographic -hdb fs.img xv6.img -m 256 xv6... cpu0: starting init: starting sh $
fsckの代わりに毎回、カーネルの入ったDISKを作り直してるって言う豪快な仕様で動いてるようです。 なお、Makefileをちょっと改変してSMPは無しで、メモリーも少なめにしてます。
ここまで動けば、次はgdb経由でもやってみたいよね。FreeBSD付属のgdbは古すぎて、xv6に接続 した途端にgdbが落ちてしまう。
portsの中を見繕ってみたら、gdb6.6とgdb7.5.1が用意されてたんで、gdb6.6を選んでみた。 /usr/local/bin/gdb66として鎮座したけど、うっかりgdbで起動するとオリジナルの古い方が動いちゃって 落ちてしまうんだ。おいらがそそっかしいだけですけど。
幸い/usr/local/binの方がPATHで優先するんで、gdb66をgdbとしてリンク張っちゃえ。けど、古い 方が起動してくる。ちょいと悩んでから、一度logoutして入り直したら、有効になってくれたよ。bashって、 起動時にPATHをスキャンして、キャシュを作ってんだな。cshにあるrehashのbash用ってのは無い のかな?
おいらも勉強
MITではOSの勉強コース番号が6.828とか言うらしくそのカリキュラムが、 6.828: Operating System Engineering として、公開されている。 あちらは秋季の入学なんで(日本も真似しようとしてるね)、入学した途端にハードが授業が 始まるんだ。このコースの終了は12月末。どんだけ詰め込み教育だい。4月でOSを教えちゃうとは。
カリュキラムを見ると、大体、水木曜日に実習(Lab)が有るみたい。日本からも参戦(加)してる 人が居て、lab1 だけをやった記録が残っている。後の実習は息が切れちゃったのかな?
そう思っていたら、息長くやっている人も居たよ。 記録壱、 記録弐、 記録参。
2010年版のソースもgitで取ってこれるんだけど、コンパイルすると、bootblockのサイズが 510バイトを超えちゃう結果となり実行は出来なかった。ArchLinuxで試したんだけど、gccが 余計な世話を焼くようになってしまったからだろうか。
今流通してるrev6版はちゃんと510バイト内に収まっているんで、ソースの所で何かダイエット でもしてるんかな? 暇にまかせて見比べてみると面白いかも。 なお、上記の記録参では、rev6版にも挑戦されてますね。頭が下がりますよ。
また、rev6版で公開されてる解説書を読まれた方がいて、その記録が xv6ソースコードリーディング として公開されています。こうなってくると資料は十分に揃っているって事で、わざわざMITへ 留学しなくても、自宅で勉強できますな。正に、インターネットは時間と場所を超越するって 事で、良い時代になったものです。
後少し資料を挙げておきます。OSが起動してくるまでの物語を扱ったxv6のブートシーケンスメモ 。創業1978年のIntel 8086に端を発し、1981年に IBM PCが発売されるや、x86が不動なものとなった。 そして、後世から見ると、きたないアーキを引きずってしぶとく生きている。世の中の プログラマーはみんな、この不条理な石に振り回されるのさ。
この石の仮想記憶を動かすコードもやはりxv6に組み込まれている訳で、そこら変を読み解く 資料が xv6を読む:アドレススペースの作成 と xv6を読む:メモリアロケータ の2本建てになって公開されてましたよ。有り難い事です。
後もう一つ、カーネル関係の*.hで定義されてる構造を分かりやすく図示した資料も こちらで公開されます。 どこの大学かと思ったら東京大学でした。MITと姉妹校なんでしょうか? オペレーティングシステム(2012年度)の下の 方にインテルのマニュアル取得のリンクがありました。
読んでみたけど、リアルモードが実モードと訳されてたりして、ちょいとピンとこない 部分も有ったので、そういう時は、Web版の Intel 80386 Reference Programmer's Manual がいいのかな。レジスタのBitアサインなんかは、 レジスターにまとまってます。 そして、このサイト経由で知った OS製作って のも面白い。
おいらは、システムプログラミングガイドを落としてきてpdftohtmlにかけてから読んでますよ。 複雑怪奇、温泉旅館の増築につぐ増築で迷路のようになってますなあ。
その点、DECは偉かった。PDP-11用に書かれたunix v6の PDP-11のブートストラップなどを 見ると、胸のつかえがすーと無くなりますよ。 PDPの流れを汲むMC68Kが流行らなかったのは、 次々と石を出すのを躊躇したモトローラのエンジニアの潔癖さに起因してるとか。 それとも、天下のIBMに嫌われたから?
まあ、68Kはワークステーションにも使われる 高級路線(MACなんて馬鹿高かったもんなあ)、それに対してx86は安価な工業用制御CPUを標榜してたから、きっとIBMは家庭用PC なら、安いに越した事は無いって判断したんだろうな?
誰か、ここらへんのつばぜり合いと言うか内幕をご存知じゃありませんかね?