Sự khác biệt trong việc thực hiện init với nhúng so với initramfs bên ngoài?


10

Tôi đang xây dựng một hệ thống Linux rất tối thiểu chỉ bao gồm kernel (v4.1-rc5) và một initramfs được điền với busybox (v1.23.2). Nó hoạt động tốt đối với hầu hết các phần, nhưng tôi quan sát thấy sự khác biệt trong hành vi thực thi lệnh trong / init cho dù tôi đang sử dụng một initramfs nhúng so với bên ngoài.

Tập lệnh / init là:

#!/bin/sh

dmesg -n 1

mount -t devtmpfs none /dev
mount -t sysfs none /sys
mount -t proc none /proc
echo "Welcome"
while true
do
    setsid cttyhack /bin/sh
done

Sau đó, tôi hoặc đặt tùy chọn CONFIG_INITRAMFS_SOURCE trong kernel .config vào thư mục chứa tất cả các thư mục cho initramfs hoặc tôi chạy

find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz

để xây dựng nó.

Sau đó, khi tôi biên dịch kernel, có hoặc không có CONFIG_INITRAMFS_SOURCE, tôi kết thúc với hai biến thể của hệ thống của mình:

  1. bzImage với initramfs được nhúng

  2. bzImage + rootfs.cpio.gz (initramfs bên ngoài)

khi tôi bắt đầu sử dụng qemu

qemu-system-x86_64 -enable-kvm -kernel bzImage

hoặc là

qemu-system-x86_64 -enable-kvm -kernel bzImage -initrd rootfs.cpio.gz

Tôi nhận được sự khác biệt sau đây trong hành vi:

với phiên bản 2 (initramfs bên ngoài) mọi thứ đều hoạt động tốt, "Chào mừng" được hiển thị và tôi nhận được lời nhắc. Tuy nhiên với phiên bản 1 (nhúng initramfs) tôi nhận được cảnh báo

unable to open an initial console

"Chào mừng" không được hiển thị và tôi nhận được lời nhắc của mình.

Theo như tôi hiểu về quy trình, hai phiên bản initramfs đó nên chứa cùng một tệp, vì tôi xây dựng nó (hoặc có kernel xây dựng nó) từ một thư mục giống hệt nhau.

Tôi tự hỏi nếu có ai có thể giúp tôi giải thích cho hành vi này?

* CẬP NHẬT *

như mikeerv đã nói trong các bình luận, kernel bao gồm một initramfs nhúng tối thiểu cho mỗi mặc định. Điều này vẫn còn khi sử dụng một cái bên ngoài, nhưng bị ghi đè nếu bạn nhúng cái của riêng bạn. Tôi thấy rằng trái với đặc điểm kỹ thuật, điều này thực sự không trống, nhưng chứa một thư mục dev, một thư mục gốc và thiết bị / dev / console. Thiết bị này sau đó được sử dụng khi sử dụng initramfs bên ngoài, nhưng được ghi đè nếu bạn nhúng chính thiết bị của mình. Vì vậy, bạn phải bao gồm thiết bị / dev / console trong nguồn initramfs của mình mknod -m 622 initramfs_src/dev/console c 5 1khi nhúng thiết bị của riêng bạn.

Cảm ơn rất nhiều đến mikeerv, frostschutz và JdeBP vì đã giúp tôi vượt qua điều đó!


Các quyền được thiết lập trên /dev/consoletrên dựng sẵn của bạn là gì? Tôi nghĩ rằng sự khác biệt có thể là về việc ai đóng gói trong hai trường hợp.
mikeerv

Một câu hỏi tương tự tất nhiên là stackoverflow.com/questions/10437995 .
JdeBP

@mikeerv thiết bị console có quyền và quyền sở hữu giống hệt nhau trong cả hai bản dựng.
clw

@JdeBP Tôi không chắc nó có giống nhau không, vì trong cả hai trường hợp tôi khởi động, đều nhận được lời nhắc và có thiết bị điều khiển. Chỉ có điều trong một init thực hiện tiếng vang và trong cái khác thì không thể.
clw

1
Làm thế nào các quyền có thể giống nhau trong initramfs nếu bạn thậm chí không có nó?
mikeerv

Câu trả lời:


2

Chúng có thực sự giống hệt nhau không?

Công cụ tích hợp mà bạn có thể tìm thấy /usr/src/linux/usr/initramfs_data.cpio.gzhoặc trích xuất nó từ bzImage như được mô tả ở đây: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

Nếu bạn sử dụng cái tích hợp đó và sử dụng nó như một cái bên ngoài thay vào đó, nó có hoạt động không?

Nếu nó vẫn khác nhau, liệu hạt nhân có giống hệt nhau không? (so sánh /proc/config.gzcho cả hai)

Cần có một số khác biệt. Tôi không biết rằng hạt nhân quan tâm đến các initramfs đến từ đâu. Tôi sớm nghi ngờ qemusử dụng các cài đặt khác nhau khi truyền -initrdtham số ...

Trên một sidenote, bạn /inittrông giống như vỏ ốc vô hạn của nó sinh ra cho tôi. setsidkhông phải là exec. Tôi có lầm không?


1
Câu trả lời này dường như là tất cả các câu hỏi.
JdeBP

1
@JdeBP: Bạn không nghĩ thứ tư!
frostschutz

1
@frostschutz Cảm ơn rất nhiều vì đã trả lời! Khi tôi sử dụng initramfs mà kernel xây dựng (usr / initramfs_data.cpio.gz) như bên ngoài, nó cũng hoạt động tốt! Ngoài ra, khi tôi cung cấp kernel đã được biên dịch với initramfs nhúng với một bên ngoài, cảnh báo sẽ xuất hiện, mặc dù bên ngoài sẽ ghi đè lên phần nhúng ( kernel.org/doc/Documentation/filesystems/ tựa ). Vì vậy, nó có lẽ cũng không phải là qemu -initrd mà là một cái gì đó bên trong hạt nhân. Tôi không thay đổi gì khác sau đó
CONFIG_INITRAMFS_SOURCE

@frostschutz Trả lời của bạn On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: Vòng lặp bắt chước getty hoặc các công cụ tương tự, kể từ khi gọi các shkhối cho đến khi lớp vỏ đó thoát ra.
stefanjunker

@stefanjunker và điều đó sẽ ổn thôi, ngoại trừ setsid hoàn toàn không chặn ...
frostschutz

1

Bạn cũng có thể quan tâm đến cách Buildroot 2018.02 xử lý vấn đề này.

Bất cứ khi nào bạn sử dụng initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y) hoặc initrd ( BR2_TARGET_ROOTFS_CPIO=n), nó sẽ thêm phần sau /initvào rootfs của bạn https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/init

#!/bin/sh
# devtmpfs does not get automounted for initramfs
/bin/mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
exec /sbin/init "$@"

Bản sao được thực hiện bởi https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/cpio.mk :

# devtmpfs does not get automounted when initramfs is used.
# Add a pre-init script to mount it before running init
define ROOTFS_CPIO_ADD_INIT
    if [ ! -e $(TARGET_DIR)/init ]; then \
        $(INSTALL) -m 0755 fs/cpio/init $(TARGET_DIR)/init; \
    fi
endef

Cũng rất hữu ích khi biết rằng đường dẫn init /initdành cho initramfs, không giống như /sbin/initcách khác: Điều gì có thể khiến việc truyền init = / path / to / chương trình vào kernel không khởi động chương trình như init?

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.