Il kernel di Linux non trova correttamente initrd


11

Avevo compilato un kernel Linux e volevo eseguirne il debug in QEMU. Ho creato un file da cui avviare eseguendo i comandi

$ qemu-img create -f raw disk.img 200M
$ mkfs.ext2 -F disk.img
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs

Poi l'ho fatto qemu -kernel bzImage -initrd disk.imge ho ottenuto lo schermo in basso che dice:

Kernel panic - not syncing: VFS: unable to mount root fs on unknown block

La mia schermata QEMU

Cosa ho fatto di sbagliato e cosa posso fare per risolverlo?



Stesso messaggio di errore di questo, ma non specifica i passaggi che ha intrapreso per raggiungerlo: unix.stackexchange.com/questions/48302/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Risposte:


8

Il kernel ti sta dicendo che non sa quale dispositivo contiene il file system di root. Il tuo loop mount non è necessario. (Smontalo prima di continuare).

Prova un comando come

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

Il -hda disk.imgparametro indica a qemu di simulare un dispositivo disco in base al proprio disk.img.

Lo -append root=/dev/sdaswitch è usato da qemu per dire al kernel del suo dispositivo root. Questo viene fatto aggiungendo root=/dev/sdaalla riga di comando del kernel. Puoi paragonarlo alla riga di comando del kernel del tuo kernel facendo cat /proc/cmdline(Questo è sicuro). Dovresti vedere anche lì un rootparametro.


Come smonterei i file?
Coder404

umount /mnt/rootfs
t-8ch

Quando lo faccio ottengo umount: / mnt / rootfs non è montato (secondo mtab)
Coder404

Presumibilmente Coder404 non vuole collegare un disco a quella macchina ed eseguire semplicemente initil file initrd. Qui stai passando disk.imgentrambi come un disco rigido e uno initrdche non ha senso.
Stéphane Chazelas

@StephaneChazelas grazie per il suggerimento -initrdche non avrebbe dovuto essere lì.
t-8ch

8

Quello che sta succedendo è che stai provando ad avviare Linux nel modo "Obsoleto". Ecco dove initrdè un ramdisk al contrario di un archivio compresso di cpio decompresso dal kernel in un ramfs e con il vecchio modo di passare al dispositivo finale.

In quella modalità, il kernel monta disk.img come ramdisk come file system radice e quindi viene eseguito /linuxrcal suo interno. Molto probabilmente nel tuo caso, non esiste tale file. Quando /linuxrc(che dovrebbe fare tutto il necessario per far apparire il dispositivo a blocchi per il vero filesystem di root) esce, allora il kernel monta il vero filesystem di root.

I messaggi sopra mostrano che monta correttamente il disco ram (1,0: 1 è per ram, quindi /dev/ram0) ma non il vero file system radice / dev / sda1 (8,1: 8 è sd, 1 è a1). Presumibilmente poiché non hai specificato una riga di comando del kernel ( -append), che /dev/sda1proviene da una CONFIG_CMDLINE passata al momento della compilazione del kernel o usando rdev.

Se il tuo disk.img è pensato per contenere un file system root, ad esempio una piccola distribuzione Linux con /sbin/init..., probabilmente vorrai invece scriverlo:

kvm -kernel kernel.img -initrd disk.img -append 'root=/dev/ram0`

Quindi, il kernel tratterà il disco ram come il vero file system root (anche se potresti ancora pivot_rootfarlo con un altro).

Per poter vedere più facilmente i messaggi del kernel, ti consiglio di usare l'output seriale:

kvm -kernel kernel.img -initrd disk.img -nographic -append "root=/dev/ram0 console=ttyS0"

In alternativa puoi usare un init ramfs invece di un 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

(a condizione che busyboxsia la versione collegata staticamente) e otterrai una shell e altre utility di busybox in quel kernel).

Si noti che il kernel ora funziona /inital contrario /linuxrco /sbin/initin quella modalità.


La riga 3 dell'output mostrato mostra che il kernel ha montato il filesystem ext2 di initramdisk. Quindi probabilmente non è un modulo mancante.
t-8ch

Oh sì, me l'ero perso, grazie @ t-8ch. Penso di sapere cosa sta succedendo e ho aggiornato la mia risposta.
Stéphane Chazelas,

0

CONFIG_BLK_DEV_INITRD=y

È richiesta anche questa opzione di configurazione del kernel. Abilita il supporto initrd sul kernel Linux.

Fortunatamente Buildroot lo imposta di default per noi quando BR2_TARGET_ROOTFS_CPIO=yviene fornito.

Quindi passare il CPIO a QEMU con l' qemu -initrdopzione. Il mio comando QEMU completo è:

./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'

Ecco un esempio minimalista di Buildroot + QEMU completamente automatizzato: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.