현재 블록 장치 드라이버를 구현하여 커널 프로그래밍을 시작하고 있습니다. "간단한" 구현을 할 수 있으며 블록 하위 시스템이 제공하는 기능에 대해 자세히 알아보고 싶습니다.
이를 위해 커널 장치 코드에서 실수를 할 때마다 개발 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
플로피 디스크에 대한 액세스를 피할 수 있습니다.