Linux 커널을 컴파일했고 이를 QEMU에서 디버깅하고 싶습니다. 명령을 실행하여 시작용 파일을 만들었습니다.
$ qemu-img create -f raw disk.img 200M
$ mkfs.ext2 -F disk.img
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs
그런 다음 나는 qemu -kernel bzImage -initrd disk.img
다음과 같은 화면을 얻었습니다.
Kernel panic - not syncing: VFS: unable to mount root fs on unknown block
내가 무엇을 잘못하고 있으며 이를 해결하려면 어떻게 해야 합니까?
답변1
무슨 일이 일어나고 있는지는 "오래된" 방식으로 Linux를 부팅하려고 한다는 것입니다. 이것은 initrd
커널에 의해 ramfs에서 압축을 풀고 이전 방법을 사용하여 터미널 장치로 전환하는 압축된 cpio 아카이브가 아닌 램디스크입니다.
이 모드에서 커널은 disk.img를 루트 파일 시스템에 램디스크로 마운트한 다음 /linuxrc
그곳에서 실행합니다. 귀하의 경우에는 그러한 파일이 없을 가능성이 높습니다. /linuxrc
(실제 루트 파일 시스템의 블록 장치를 부팅하는 데 필요한 모든 작업을 수행해야 함)이 종료되면 커널은 실제 루트 파일 시스템을 마운트합니다 .
위 메시지는 램 디스크(1,0:1은 을 나타냄)를 성공적으로 마운트했지만 ram
실제 /dev/ram0
루트 파일 시스템인 /dev/sda1(8,1:8은 을 나타냄 sd
, 1은 을 나타냄 a1
)을 마운트하지 않았음을 나타냅니다. 아마도 커널 명령줄( -append
) 을 지정하지 않았기 때문에 /dev/sda1
커널을 컴파일하거나 rdev
.
disk.img가 소규모 Linux 배포판과 같은 루트 파일 시스템을 포함하려는 경우 /sbin/init
대신 작성할 수 있습니다.
kvm -kernel kernel.img -initrd disk.img -append 'root=/dev/ram0`
그러면 커널은 RAM 디스크를 실제 루트 파일 시스템으로 처리합니다( pivot_root
다른 파일 시스템을 사용할 수도 있음).
커널 메시지를 더 쉽게 보려면 직렬 출력을 사용하는 것이 좋습니다.
kvm -kernel kernel.img -initrd disk.img -nographic -append "root=/dev/ram0 console=ttyS0"
대안으로 init ramdisk 대신 init ramfs를 사용할 수 있습니다.
mkdir -p RAMFS/{bin,dev}
cd RAMFS/bin
cp /bin/busybox .
"$PWD/busybox" --install .
cd ..
cp -a /dev/{null,tty,zero,console} dev
printf '%s\n' "#! /bin/sh -" "exec /bin/sh" > init
chmod +x init
find . | cpio -oHnewc | gzip > ../initramfs.gz
cd ..
kvm -kernel kernel.img -initrd initramfs.gz
(정적으로 링크된 버전이 제공됩니다 busybox
.) 이 커널에서 쉘과 기타 비지박스 유틸리티를 얻을 수 있습니다.
이제 커널은 이 모드 /init
와 반대로 작동합니다 /linuxrc
./sbin/init
답변2
커널은 어떤 것이 무엇인지 모른다고 알려줍니다.장비루트 파일 시스템을 저장합니다. 설치 루프가 필요하지 않습니다. (계속하기 전에 제거하십시오).
다음과 같은 명령을 시도해 보세요
qemu -kernel bzImage -hda disk.img -append root=/dev/sda
이 -hda disk.img
매개변수는 qemu에게 disk.img
.
-append root=/dev/sda
qemu는 이 스위치를 사용하여 커널에 루트 장치를 알려줍니다. 이는 커널 명령줄에 추가하여 root=/dev/sda
수행 됩니다. 다음을 수행하여 이를 자신의 커널 커널 명령줄 cat /proc/cmdline
(안전함)과 비교할 수 있습니다. 또한 거기에 매개변수가 있다는 것도 확인해야 합니다 root
.
답변3
CONFIG_BLK_DEV_INITRD=y
이 커널 구성 옵션도 필요합니다. Linux 커널에서 initrd 지원을 활성화합니다.
BR2_TARGET_ROOTFS_CPIO=y
다행스럽게도 Buildroot는 주어진 경우 기본적으로 이를 설정합니다.
그런 다음 이 옵션을 사용하여 CPIO를 QEMU에 전달할 수 있습니다 qemu -initrd
. 내 완전한 QEMU 명령은 다음과 같습니다.
./buildroot/output.x86_64~/host/usr/bin/qemu-system-x86_64 -m 128M -monitor telnet::45454,server,nowait -netdev user,hostfwd=tcp::45455-:45455,id=net0 -smp 1 -M pc -append ' nopat nokaslr norandmaps printk.devkmsg=on printk.time=y console=ttyS0' -device edu -device lkmc_pci_min -device virtio-net-pci,netdev=net0 -kernel ./buildroot/output.x86_64~/images/bzImage -nographic -initrd './buildroot/output.x86_64~/images/rootfs.cpio'
다음은 간단하고 완전히 자동화된 Buildroot + QEMU 예입니다.https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd