เคอร์เนล Linux ไม่พบ initrd อย่างถูกต้อง


11

ฉันได้รวบรวมเคอร์เนล 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

หน้าจอ QEMU ของฉัน

ฉันทำอะไรผิดและฉันต้องแก้ไขอย่างไร



ข้อความแสดงข้อผิดพลาดเช่นเดียวกันนี้ แต่ไม่ได้ระบุขั้นตอนที่เขาดำเนินการถึง: unix.stackexchange.com/questions/48302/…
Ciro Santilli 冠状病毒审查审查六四事件法轮功

คำตอบ:


8

เคอร์เนลกำลังบอกคุณว่ามันไม่ทราบว่าอุปกรณ์ใดเก็บระบบไฟล์รูท ไม่จำเป็นต้องติดตั้งลูปของคุณ (ถอนติดตั้งก่อนดำเนินการต่อ)

ลองใช้คำสั่งเช่น

qemu -kernel bzImage -hda disk.img -append root=/dev/sda

-hda disk.imgพารามิเตอร์บอก qemu disk.imgเพื่อจำลองอุปกรณ์ดิสก์ที่อยู่บนพื้นฐานของคุณ

-append root=/dev/sdaสวิทช์จะถูกใช้โดย qemu จะบอกเคอร์เนลเกี่ยวกับมันเป็นอุปกรณ์ราก สิ่งนี้ทำได้โดยการต่อท้ายคำroot=/dev/sdaสั่งเคอร์เนล คุณสามารถเปรียบเทียบสิ่งนี้กับ commandline kernel ของเคอร์เนลของคุณเองโดยทำcat /proc/cmdline(สิ่งนี้ปลอดภัย) คุณควรเห็นrootพารามิเตอร์ด้วยเช่นกัน


ฉันจะยกเลิกการต่อเชื่อมไฟล์ได้อย่างไร
Coder404

umount /mnt/rootfs
t-8ch

เมื่อฉันทำสิ่งที่ฉันได้รับ umount: / mnt / rootfs ไม่ได้ติดตั้ง (ตาม mtab)
Coder404

สันนิษฐาน Coder404 ไม่ต้องการที่จะแนบดิสก์ไปยังเครื่องที่และเพียงแค่เรียกใช้ในinit initrdที่นี่คุณกำลังส่งผ่านdisk.imgทั้งฮาร์ดดิสก์และinitrdที่ไม่สมเหตุสมผล
Stéphane Chazelas

@ StephanChazelas ขอบคุณเกี่ยวกับคำแนะนำเกี่ยวกับ-initrdสิ่งที่ไม่ควรมี
t-8ch

8

สิ่งที่เกิดขึ้นคือคุณกำลังพยายามบูท Linux ด้วยวิธี "เลิกใช้" นั่นคือที่ที่initrdเป็น ramdisk ซึ่งตรงข้ามกับที่เก็บถาวร cpio ที่ถูกบีบอัดโดยคลายเคอร์เนลใน ramfs และด้วยวิธีเก่าในการสลับไปยังอุปกรณ์ปลายทาง

ในโหมดนั้นเคอร์เนลจะเมานต์ disk.img เป็น ramdisk เป็นระบบไฟล์รูทและดำเนินการ/linuxrcในนั้น ในกรณีของคุณไม่มีไฟล์ดังกล่าว เมื่อ/linuxrc(ซึ่งควรจะทำสิ่งที่จำเป็นในการนำอุปกรณ์บล็อกสำหรับระบบไฟล์รูทจริง) ออกจากนั้นเคอร์เนลจะเมาท์ระบบไฟล์รูทจริง

ข้อความข้างต้นแสดงให้เห็นว่ามันติดตั้ง ram disk เรียบร้อยแล้ว (1,0: 1 มีไว้สำหรับramดังนั้น/dev/ram0) แต่ไม่ใช่ระบบไฟล์รูทจริง / dev / sda1 (8,1: 8 คือsd, 1 คือa1) สันนิษฐานว่าเนื่องจากคุณไม่ได้ระบุบรรทัดคำสั่งเคอร์เนล ( -append) ที่/dev/sda1มาจาก CONFIG_CMDLINE 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 ramfs แทน init ramdisk:

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เป็นรุ่นที่เชื่อมโยงแบบคงที่) และคุณจะได้รับเชลล์และโปรแกรมอรรถประโยชน์ busybox อื่น ๆ ในเคอร์เนลนั้น

โปรดทราบว่าขณะนี้เคอร์เนลทำงาน/initเหมือน/linuxrcหรือตรงข้ามกับ/sbin/initโหมดนั้น


บรรทัดที่ 3 ของผลลัพธ์ที่แสดงแสดงให้เห็นว่าเคอร์เนลติดตั้งระบบไฟล์ ext2 ของ initramdisk ดังนั้นมันอาจจะไม่ใช่โมดูลที่ขาดหายไป
t-8ch

โอ้ใช่ฉันพลาดไปแล้วขอบคุณ @ t-8ch ฉันคิดว่าฉันรู้ว่าเกิดอะไรขึ้นและอัพเดตคำตอบของฉันแล้ว
Stéphane Chazelas

0

CONFIG_BLK_DEV_INITRD=y

ต้องใช้ตัวเลือกการกำหนดค่าเคอร์เนลนี้ มันเปิดใช้งานการสนับสนุน initrd บนเคอร์เนล Linux

Buildroot โชคดีที่ตั้งค่าเริ่มต้นสำหรับเราเมื่อBR2_TARGET_ROOTFS_CPIO=yได้รับ

จากนั้นคุณจะส่ง 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.