現在、ブロックデバイスドライバを実装してカーネルプログラミングを開始しています。 「簡単な」実装が可能で、ブロックサブシステムが提供する機能の詳細を知りたいです。
そのために、カーネルデバイスコードで間違いを犯すたびに開発OSがクラッシュするのを防ぐために、qemuを使って私のOSをエミュレートしたいと思います。
ホストシステムの構成
私のワークステーションでは、カーネル4.9.0を実行するDebian 9を使用しています。
$ uname -a
Linux PC325 4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux
ミラーディスク製作
仮想マシンを生成するために、500Mの生イメージを作成しました。dd if=/dev/zero of=vm-image.raw bs=1M count=512
次に、次のコマンドを使用してext4としてフォーマットします。mkfs.ext4 vm-image.raw
@ meuhコメント以降に更新されました:
次に、次のようにディスクイメージを埋めます。
mount vm-image.raw /mnt
mkdir /mnt/dev /mnt/lib /mnt/proc /mnt/root /mnt/run /mnt/sbin /mnt/sys
cp -r /etc /mnt/
cp -r /lib/systemd /mnt/lib
ln -s /lib/systemd/systemd /mnt/sbin/init
これで、エミュレートされたOSを起動しようとしていますが、設定にいくつかの問題があります。
コマンドの実行
$ qemu-system-x86_64 -k fr -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) -hda vm/vm-image.raw -append "initrd=/boot/initrd.img-$(uname -r) root=/dev/sda rw console=ttyS0" -nographic
ガイドトラッキング
[...] Kernel boot sequence [...]
Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [ 2.015241] tsc: Refined TSC clocksource calibration: 3392.292 MHz
[ 2.016768] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x30e5dd94d34, max_idle_ns: 440795304975 ns
[ 2.895630] random: fast init done
Begin: Waiting for suspend/resume device ... Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
[ 11.111765] random: crng init done
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
done.
Gave up waiting for suspend/resume device
done.
Begin: Will now check root file system ... fsck from util-linux 2.29.2
[/sbin/fsck.ext4 (1) -- /dev/sda] fsck.ext4 -a -C0 /dev/sda
/dev/sda: clean, 3607/32768 files, 12617/131072 blocks
done.
[ 35.528453] EXT4-fs (sda): mounted filesystem with ordered data mode. Opts: (null)
done.
Begin: Running /scripts/local-bottom ... done.
Begin: Running /scripts/init-bottom ... done.
run-init: /sbin/init: No such file or directory
[ 35.569247] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[ 35.569247]
[ 35.570469] CPU: 0 PID: 1 Comm: run-init Not tainted 4.9.0-6-amd64 #1 Debian 4.9.82-1+deb9u3
[ 35.571599] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[ 35.572695] 0000000000000000 ffffffff9792e074 ffff974c05e14d00 ffffa66e8003feb8
[ 35.573741] ffffffff9777cfbd ffff974c00000010 ffffa66e8003fec8 ffffa66e8003fe60
[ 35.574780] a4112d94e56af84a ffff974c05e14d80 0000000000000100 ffff974c05e84490
[ 35.575793] Call Trace:
[ 35.576132] [<ffffffff9792e074>] ? dump_stack+0x5c/0x78
[ 35.576815] [<ffffffff9777cfbd>] ? panic+0xe4/0x23f
[ 35.577453] [<ffffffff9767c2de>] ? do_exit+0xade/0xae0
[ 35.578136] [<ffffffff978058b4>] ? vfs_write+0x144/0x190
[ 35.578830] [<ffffffff9767c313>] ? SyS_exit+0x13/0x20
[ 35.579510] [<ffffffff97603b7f>] ? do_syscall_64+0x8f/0xf0
[ 35.580223] [<ffffffff97c113b8>] ? entry_SYSCALL_64_after_swapgs+0x42/0xb0
[ 35.581209] Kernel Offset: 0x16600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 35.582584] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[ 35.582584]
質問
1 - フロッピーデバイスを読み取ろうとしています。
起動時にカーネルが存在しないか、または読み取れないフロッピーデバイスからデータを読み取ろうとするようです。 30回の試みの後にカーネルがあきらめたので深刻な問題ではありませんでしたが、ブートシーケンスが30秒ほど遅くなりました。
オプションを使用してqemuを実行してみましたが、-no-fd-bootchk
何も変更されませんでした。
修正する:-fda floppy.img
1koのゼロ化された生の画像で、フロッピー関連floppy.img
のエラーメッセージを正確に抑制し、起動時に最大20秒を節約します。ただし、ブートトレースに見られるように、/scripts/local-block
まだ数回実行され、次のステップに移動するのに最大10秒かかります。
2 - システムを初期化できません。
@ meuhコメント以降に更新されました:
カーネルが有効な初期化スクリプトを見つけることができないようです。ただし、/sbin/init
ディスクイメージに存在し、へのシンボリックリンクです/lib/systemd/systemd
。
カーネルパニックが発生するのに原因が何であるかわかりません。
質問
私はqemuに最初に触れていて、エミュレーションシステムが動作するのにほとんど近づいているようですが、もう得られません。
私はパラメータを試しましたが、完全に起動し、initramdiskプロンプトの代わりにbashプロンプトを表示するソリューションが見つかりませんでした。
@ meuhコメント以降に更新されました:
システムを初期化するには、ディスクイメージに何をコピーする必要がありますか?
答え1
一般に、人々はisoまたは既存のqemuイメージからqemuをインストールしているため、まだこれを行っていないため、以下より簡単な方法があります。欠落しているのは、必要なファイルシステムとほぼ同じです。chroot。
一つ試してみるのは
sudo debootstrap --arch=amd64 unstable ~/debian-tree/
約300MBのサイズのファイルを削除して解凍した後、システムコンテナに「実行」してテストできます。
sudo systemd-nspawn -D ~/debian-tree/ -b
望むよりman machinectl
。 qemuイメージをブロックデバイスとして作成してマウントできます。
sudo apt-get install qemu-utils
sudo modprobe nbd
ls /dev/nbd* # gives /dev/nbd0 /dev/nbd1 ...
sudo qemu-nbd -c /dev/nbd0 /my/vm-image
sudo mount /dev/nbd0 /mnt/... # nbd0p1 if you have partitioned
sudo rsync -HSaxX ~/debian-tree/ /mnt/...
そして、このツリーをそこにコピーしてください。 qemuを実行するときに競合を防ぐために、通常はより大きなVMサイズを提供する必要があります。
qemu-system-x86_64 -m 512M ... -machine pc,accel=kvm -cpu host -enable-kvm
これにより、-boot d
フロッピーディスクへのアクセスを回避できます。