Nhân Linux không tìm thấy initrd chính xác


11

Tôi đã biên dịch kernel linux và tôi muốn gỡ lỗi nó trong QEMU. Tôi đã tạo một tệp để khởi động từ bằng cách thực hiện các lệnh

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

Sau đó, tôi đã làm qemu -kernel bzImage -initrd disk.imgvà có màn hình bên dưới có nội dung:

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

Màn hình QEMU của tôi

Tôi đã làm gì sai và tôi có thể làm gì để khắc phục nó?



Thông báo lỗi tương tự như thế này, nhưng không chỉ định các bước anh ta đã thực hiện để tiếp cận nó: unix.stackexchange.com/questions/48302/ Kẻ
Ciro Santilli 病毒 审查 六四 事件 法轮功

Câu trả lời:


8

Nhân nói với bạn rằng nó không biết thiết bị nào chứa hệ thống tập tin gốc. Gắn kết vòng lặp của bạn là không cần thiết. (Tháo nó trước khi tiếp tục).

Hãy thử một lệnh như

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

Các -hda disk.imgtham số kể Qemu để mô phỏng một thiết bị đĩa dựa trên của bạn disk.img.

Công -append root=/dev/sdatắc được qemu sử dụng để nói với kernel về thiết bị gốc của nó. Điều này được thực hiện bằng cách nối thêm root=/dev/sdadòng lệnh kernel. Bạn có thể so sánh điều này với dòng lệnh kernel của kernel của riêng bạn bằng cách thực hiện cat /proc/cmdline(Điều này an toàn). Bạn cũng sẽ thấy ở đó một roottham số.


Làm thế nào tôi có thể ngắt kết nối các tập tin?
Coder404

umount /mnt/rootfs
t-8ch

Khi tôi làm điều đó, tôi nhận được umount: / mnt / rootfs không được gắn kết (theo mtab)
Coder404

Có lẽ Coder404 không muốn gắn đĩa vào máy đó và chỉ chạy inittrong initrd. Ở đây bạn đang vượt qua disk.imgcả hai như một đĩa cứng và initrdkhông có ý nghĩa gì.
Stéphane Chazelas

@StephaneChazelas cảm ơn về gợi ý về -initrdđiều không nên có ở đó.
t-8ch

8

Điều gì đang xảy ra là bạn đang cố gắng khởi động Linux theo cách "lỗi thời". Đó là nơi mà initrdmột ramdisk trái ngược với kho lưu trữ cpio đã nén được giải nén bởi kernel trong một ramfs, và với cách cũ để chuyển sang thiết bị cuối.

Trong chế độ đó, kernel gắn đĩa.img dưới dạng ramdisk làm hệ thống tập tin gốc và sau đó thực thi /linuxrctrong đó. Rất có thể trong trường hợp của bạn, không có tập tin nào như vậy. Khi /linuxrc(được cho là làm bất cứ điều gì cần thiết để đưa thiết bị khối cho hệ thống tập tin gốc thực sự) thoát ra, thì nhân gắn kết hệ thống tập tin gốc thực sự.

Các thông báo ở trên cho thấy rằng nó gắn đĩa ram thành công (1,0: 1 là ramvì vậy /dev/ram0) nhưng không phải là hệ thống tập tin gốc thực sự / dev / sda1 (8.1: 8 là sd, 1 là a1). Có lẽ vì bạn đã không chỉ định một dòng lệnh kernel ( -append), /dev/sda1xuất phát từ CONFIG_CMDLINE được truyền vào thời gian biên dịch kernel hoặc sử dụng rdev.

Nếu đĩa.img của bạn có nghĩa là chứa một hệ thống tệp gốc có nghĩa là một bản phân phối Linux nhỏ với /sbin/init..., thì có lẽ bạn muốn viết nó thay thế:

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

Sau đó, kernel sẽ coi đĩa ram là hệ thống tập tin gốc thực sự (mặc dù bạn vẫn có thể pivot_rootđến một cái khác).

Để có thể xem các thông điệp kernel dễ dàng hơn, tôi khuyên bạn nên sử dụng đầu ra nối tiếp:

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

Để thay thế, bạn có thể sử dụng ram ram init thay vì 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

(được cung cấp busyboxlà phiên bản được liên kết tĩnh) và bạn sẽ nhận được một shell và các tiện ích busybox khác trong kernel đó).

Lưu ý rằng kernel bây giờ chạy /initngược lại /linuxrchoặc /sbin/inittrong chế độ đó.


Dòng 3 của đầu ra được hiển thị cho thấy, kernel đã gắn hệ thống tập tin ext2 của initramdisk. Vì vậy, nó có thể không phải là một mô-đun bị thiếu.
t-8ch

Ồ vâng, tôi đã bỏ lỡ điều đó, cảm ơn @ t-8ch. Tôi nghĩ rằng tôi biết những gì đang xảy ra và đã cập nhật câu trả lời của tôi.
Stéphane Chazelas

0

CONFIG_BLK_DEV_INITRD=y

Tùy chọn cấu hình kernel này cũng được yêu cầu. Nó cho phép hỗ trợ initrd trên kernel Linux.

May mắn thay Buildroot đặt nó theo mặc định cho chúng tôi khi BR2_TARGET_ROOTFS_CPIO=yđược đưa ra.

Sau đó, bạn chuyển CPIO cho QEMU với qemu -initrdtùy chọn. Lệnh QEMU đầy đủ của tôi là:

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

Dưới đây là một ví dụ Buildroot + QEMU hoàn toàn tự động tối giản: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.