Linux çekirdeği initrd'i doğru bulmuyor


11

Bir linux çekirdeği derlemiştim ve QEMU'da hata ayıklamak istedim. Komutları yaparak önyükleme yapmak için bir dosya oluşturdum

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

Sonra yaptım qemu -kernel bzImage -initrd disk.imgve aşağıdaki ekran var:

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

QEMU ekranım

Neyi yanlış yaptım ve düzeltmek için ne yapabilirim?



Yanıtlar:


8

Çekirdek size hangi cihazın kök dosya sistemini tuttuğunu bilmediğini söylüyor . Döngü bağlantınız gerekli değildir. (Devam etmeden önce bağlantısını kesin).

Gibi bir komut deneyin

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

-hda disk.imgParametresi ilgili temelinde disk cihazını simüle etmek qemu söyler disk.img.

-append root=/dev/sdaAnahtar 's kök aygıt hakkında çekirdek anlatmak için qemu tarafından kullanılır. Bu işlem root=/dev/sdaçekirdek komut satırına eklenerek yapılır . Bunu yaparak kendi çekirdeğinizin çekirdek komut satırı ile karşılaştırabilirsiniz cat /proc/cmdline(Bu güvenli). Orada da bir rootparametre görmelisiniz .


Dosyaları nasıl kaldırabilirim?
Coder404

umount /mnt/rootfs
t-8ch

Bunu yaptığımda umount alıyorum: / mnt /
rootfs

Tahminen Coder404 o makineye bir disk takmak ve sadece çalıştırmak istemiyor initiçinde initrd. Burada disk.imgher ikisini de bir sabit disk olarak geçiriyorsunuz ve bu bir initrdanlam ifade etmiyor.
Stéphane Chazelas

@StephaneChazelas bununla ilgili ipucu için teşekkürler -initrd.
t-8ch

8

Olan şu ki, Linux'u "Eskimiş" şekilde başlatmaya çalışıyorsunuz. Bu, initrdbir ramfs içinde çekirdek tarafından paketlenmiş sıkıştırılmış bir cpio arşivinin aksine ve son aygıta geçmenin eski yolunun bir ramdisk olduğu yerdir .

Bu modda çekirdek, disk.img dosyasını kök dosya sistemi olarak ramdisk olarak bağlar ve ardından burada yürütülür /linuxrc. Büyük ihtimalle sizin durumunuzda böyle bir dosya yok. Ne zaman /linuxrcçıkışlar, (gerçek kök dosya sistemi için blok aygıtı getirmek için gerekli her şeyi yapma gerekiyordu) ardından çekirdek gerçek kök dosya sistemini bağlar.

Yukarıdaki mesajlar, ram diskini başarılı bir şekilde bağladığını (1,0: 1 içindir ram, /dev/ram0ancak) gerçek kök dosya sistemi / dev / sda1'i (8,1: 8 sd, 1'dir a1) göstermektedir. Muhtemelen bir çekirdek komut satırı ( -append) belirtmediğiniz için /dev/sda1, çekirdek derleme zamanında veya kullanarak bir CONFIG_CMDLINE'dan gelir rdev.

Disk.img'iniz /sbin/init... ile küçük bir Linux dağıtımı diyelim bir kök dosya sistemi içeriyorsa , bunun yerine muhtemelen yazmak istersiniz:

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

Daha sonra çekirdek, ram diskine gerçek kök dosya sistemi gibi davranır (yine pivot_rootde başka bir tanesine olabilir).

Çekirdek mesajlarını daha kolay görebilmek için seri çıktıyı kullanmanızı tavsiye ederim:

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

Alternatif olarak, init ramdisk yerine init ramfs kullanabilirsiniz:

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

( busyboxstatik olarak bağlı sürümdür) ve o çekirdekteki bir kabuk ve diğer meşgul kutusu yardımcı programlarını alırsınız).

Çekirdeğin artık bu modun /initaksine /linuxrcveya /sbin/initbu modda çalıştığını unutmayın .


Gösterilen çıktının 3. satırı, çekirdeğin initramdisk'in ext2 dosya sistemini monte ettiğini gösterir. Yani muhtemelen eksik bir modül değil.
t-8ch

Oh evet, bunu kaçırmıştım, teşekkürler @ t-8ch. Sanırım neler olduğunu biliyorum ve cevabımı güncelledim.
Stéphane Chazelas

0

CONFIG_BLK_DEV_INITRD=y

Bu çekirdek yapılandırma seçeneği de gereklidir. Linux çekirdeğinde initrd desteği sağlar.

Neyse ki Buildroot BR2_TARGET_ROOTFS_CPIO=y, verildiğinde bizim için varsayılan olarak ayarlar .

Daha sonra qemu -initrdseçeneği ile CPIO'yu QEMU'ya iletirsiniz . Tam QEMU komutum:

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

İşte minimalist tam otomatik bir Buildroot + QEMU örneği: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.