Ядро Linux неправильно знаходить інітард


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до командного рядка ядра. Ви можете порівняти це з командним рядком власного ядра, зробивши це cat /proc/cmdline(Це безпечно). Ви повинні побачити там і rootпараметр.


Як би я відключив файли?
Coder404

umount /mnt/rootfs
t-8ch

Коли я це роблю, я отримую umount: / mnt / rootfs не змонтований (згідно з mtab)
Coder404,

Імовірно, Coder404 не хоче приєднувати диск до цієї машини, а просто запустити initв initrd. Тут ви передаєте disk.imgяк жорсткий диск, так і initrdбез сенсу.
Стефан Шазелас

@StephaneChazelas дякує про натяк на -initrdте, що цього не повинно було бути.
t-8ch

8

Що відбувається, це те, що ви намагаєтеся завантажувати Linux "застарілим" способом. Саме тут initrdє ramdisk на відміну від стисненого архіву cpio, розпакованого ядром у рамці, та зі старим способом переключення на кінцевий пристрій.

У цьому режимі ядро ​​монтує disk.img як ramdisk як кореневу файлову систему, а потім виконує /linuxrcтам. Швидше за все, у вашому випадку такого файлу немає. Коли /linuxrc(який повинен зробити все необхідне для виведення блокового пристрою для реальної кореневої файлової системи), ядро ​​монтує реальну кореневу файлову систему.

Повідомлення, наведені вище, показують, що він успішно монтує оперативний диск (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`

Тоді ядро ​​розглядало б оперативні диски як справжню кореневу файлову систему (хоча ви все ще 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статично пов'язана версія), і ви отримаєте оболонку та інші утиліти зайнятих у цьому ядрі).

Зауважте, що ядро ​​зараз працює /initна відміну від цього режиму /linuxrcабо /sbin/initв цьому режимі.


У рядку 3 показаного виводу видно, що ядро ​​монтувало файлову систему ext2 initramdisk. Тож це, мабуть, не відсутній модуль.
t-8ch

О так, я це пропустив, дякую @ t-8ch. Я думаю, що я знаю, що відбувається, і оновив свою відповідь.
Стефан Шазелас

0

CONFIG_BLK_DEV_INITRD=y

Цей параметр налаштування ядра також необхідний. Це дозволяє підтримувати initrd в ядрі Linux.

Luckly 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.