おまぬけ活動日誌

最近のツッコまれどころ

この日誌から Google してもらう


2008年11月20日(Thu) いい天気だが嵐が来るのだそうだ [同日]

[DocoMomo] qemuでブートできるディスクのイメージをつくる (成功編)

フラッシュメモリに書き込まずにDocoMomoを試したいと思いついて幾星霜(というほどでもないけれど)、 grubにinstallしてもらうにはBIOSがディスクのことを知ってないといけないと気づいて*1、 自分でディスクのイメージを組み立てることにしました。

stage1のイメージをディスクの最初に起くべきなのは知っていたのですが、 それだけでは、 画面じゅうGRUBで埋め尽される。 stage1.5があればディスク上の位置ではなくファイルシステム内のパスからstage2を探せそうだとわかっても、 素のstage1からstage1.5を起動できない。 いっぽう、GRUBでブートするためのフロッピーのイメージを作るには、 stage1とstage2をただ連結すればいい*2のだけれど、 stage2はでかすぎてハードディスクのMBR直後の空き領域には入らない、 という問題がありました。

LinuxにおけるMBRのまとめとバックアップ方法 - adsaria moodなどを参考にさせていただきつつ やっと閃いたのは、qemu専用にディスクのイメージをつくるからこそできる方法で、 でかいstage2をstage1の直後に置いて、そこにはファイルシステムの入ってるパーティションを起かないようにするという方法でした。 普通のインストール方法でこれを使うときっとインストーラが0シリンダ目からパーティションを切っちゃってstage2の場所がなくなる。

というわけで、fat16のパーティションにkernelとinitrdを置いてqemuの中でrun level 1まで行けるように確認できたのが下記のスクリプトです。

PHONY: create-qemu-image
create-qemu-image: $(tmp_dir)/qemu-hd0.img
$(tmp_dir)/qemu-hd0.img:
	# Creating an hd image of 512 bytes/sector, 32 heads, and 63 sectors/track
	# Using a copy of the vanilla stage1 as a template MBR with partition table
	cp /usr/share/grub/i386-momonga/stage1 $(tmp_dir)/qemu-hd0-0.img
	# Inflating stage2, which must follow stage1, to a cylinder boundary
	# stage2 of size <= 512*32*63-512 = 1031680 bytes and stage1 occupy 1 cyl
	dd if=/usr/share/grub/i386-momonga/stage2 of=$(tmp_dir)/qemu-hd0-1.img bs=1031680 count=1 conv=sync
	# Creating first partition of 511.875 MB or 520 cylinders
	# TODO: copy DocoMomo files into this
	/sbin/mkdosfs -C $(tmp_dir)/qemu-hd0-2.img 1048320
	# Creating partition table - please ignore errors related to ioctl
	echo '1,520,6,*' | /sbin/sfdisk -C 521 -H 32 -S 63 $(tmp_dir)/qemu-hd0-0.img
	# Merging
	cat $(tmp_dir)/qemu-hd0-0.img $(tmp_dir)/qemu-hd0-1.img $(tmp_dir)/qemu-hd0-2.img > $(tmp_dir)/qemu-hd0.img 

ポイントはsfdiskへの入力でパーティションのはじまりが0ではなくて1のところ。この途中で$(tmp_dir)/qemu-hd0-2.imgをループバックマウントしてkernelとinitrdを入れてやりました。

こういうパズルは楽しいです。マニュアルとコード読め、と言われそうだけど。

で。この記事を書きつつ自分のメモをふりかえって見ると、Re: Installing grub into the mbr of a disk imageより、実は、

grub>device (hd3) /path/to/your/disk/image

でGRUBに、BIOSが知らないハードディスクイメージにインストールをしてもらえる?うーん…まあ頭の体操、ということで。(hd3)の数字だってマシンによってどこまで増やせばいいかわからないしね、ね。

*1 実はそうではなかったかも。この記事の最後を参照のこと。

*2 info grub

[run] CSO+76+行き止まり+CSO延長 1時間02分43秒

新しい靴。すげい呼吸器リミット。少し皮膚消化器リミット。

汚い話でもうしわけないけれど、どばっと痰が出た。これで体調が良くなると良いのだけれど。

sedとかgrepとかの速度

DocoMomoのためのRPMパッケージのダウンロードが全然進まないので試してみた。

sed-4.1.5-1m.mo4、grep-2.5.1a-1m.mo4、ruby-1.8.6.111-4m.mo4、perl-5.8.8-14m.mo4。 検索対象はビデオカメラを選ぶ時にサンプルとしてダウンロードしたMP4のファイル(13MB)。 下記のようなコマンドでuser時間を記録した。

1回ずつしか試してないけど。

$ LANG=<LANG> /usr/bin/time sed -n /hello/p 対象ファイル
$ LANG=<LANG> /usr/bin/time grep hello 対象ファイル
$ LANG=<LANG> /usr/bin/time ruby -ne 'puts $_ if /hello/ =~ $_' 対象ファイル
$ LANG=<LANG> /usr/bin/time perl -ne '/hello/ && print' 対象ファイル

今回使ったファイルではどのやりかたでも「hello」の含まれる行はみつからなかった。

LANGCja_JP.EUC-JPja_JP.UTF-8en_USen_US.UTF-8
grep0.010.971.060.011.06
sed0.101.381.040.101.06
ruby0.150.140.150.150.15
perl0.130.130.130.120.12

sedもgrepも文字コードに依存して速度が違う。 言語には依存してないみたい。 perlとrubyでは文字コードや言語による違いは無かった。

pythonは同等なワンライナーをすぐに思い付けなかったので無し。スミマセン。

(追記) ときどきの雑記帖 i戦士篇より、sedやgrepは「マッチングの際にバイト文字列をワイド文字に変換しながら、 ワイド文字基準で動作する」のだそうです。変換する分だけ遅くなる、と、「食わせたデータバイナリ(MP4)なんですね。 だとすると、上の説明にある mbrtowc で変換エラーを頻発しているはずなので 信頼性にちょっとかけるデータかも」。あう。そうですね。何か良いテキストファイルはないかな…。それはそうと、Pythonはロケールによっては起動するときに読み込むモジュールが増えるので起動が遅くなる、という実験をしたことがあったような気がしたのですが、なんだか曖昧な結論しか残ってませんでした。3年前のPythonだし、今は違うのかも。

本日のツッコミ(全1件) [ツッコミを入れる]
> okuji (2008年11月22日(Sat) 03:36)

デバイスの番号はBIOSの起動時に合わせるだけです。grub shellに任せるのが絶対楽です。<br><br>ちなみに、私がGRUB2の開発で使っているシェルスクリプトはこんな感じです。コメント多くてすみません。<br><br>#! /bin/sh<br><br>#file=$HOME/hobby/grub2/objs/floppy.img<br>file=$HOME/hobby/grub2/objs/hd.img<br><br>make || exit 1<br>./grub-mkimage -d . -v -o core.img biosdisk _chain ext2 pc gpt<br>parted -s hd.img mklabel msdos<br>parted -s hd.img mkpartfs primary ext2 0 10<br>#mkdosfs $file<br>#mke2fs -F $file<br>#sudo mount -o loop -t ext2 $file /mnt/loop<br>sudo mount -o loop,offset=16384 -t ext2 $file /mnt/loop<br>sudo mkdir -p /mnt/loop/boot/grub<br>sudo cp boot.img core.img *.mod moddep.lst command.lst fs.lst /mnt/loop/boot/grub || exit 1<br>#test -f grub.cfg && gzip -c grub.cfg | sudo dd of=/mnt/loop/grub.cfg.gz<br>test -f grub.cfg && sudo cp -f grub.cfg /mnt/loop/boot/grub<br>#sudo ./grub-setup -d /mnt/loop/boot/grub -v -r '(fd0)' -m device.map '(fd0)'<br>sudo ./grub-setup -d /mnt/loop/boot/grub -v -r '(hd0,1)' -m device.map '(hd0)'<br>sudo umount /mnt/loop


作り手とその取り巻きだけが楽しんでる間は本物じゃない。その中身が理解できない人々の生活を変えてこそ本物だ


zunda <zunda at freeshell.org>