ความแตกต่างในการดำเนินการของ init กับแบบฝังตัวกับแบบเริ่มต้นภายนอก?


10

ฉันกำลังสร้างระบบลีนุกซ์ที่น้อยมากซึ่งเพิ่งประกอบไปด้วยเคอร์เนล (v4.1-rc5) และ initramfs ที่บรรจุด้วย busybox (v1.23.2) มันใช้งานได้ดีส่วนใหญ่ แต่ฉันสังเกตเห็นความแตกต่างในพฤติกรรมของการดำเนินการคำสั่งใน / init ไม่ว่าฉันจะใช้ initramfs ฝังตัวกับภายนอก

สคริปต์ / init คือ:

#!/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

จากนั้นฉันจะตั้งค่าตัวเลือก CONFIG_INITRAMFS_SOURCE ในเคอร์เนล. config ไปยังไดเรกทอรีที่มีโฟลเดอร์ทั้งหมดสำหรับ initramfs หรือฉันเรียกใช้

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

เพื่อสร้างมัน

เมื่อฉันคอมไพล์เคอร์เนลไม่ว่าจะมีหรือไม่มีชุด CONFIG_INITRAMFS_SOURCE ฉันก็จบลงด้วยสองตัวแปรในระบบของฉัน:

  1. bzImage ที่มี initramfs ฝังอยู่

  2. bzImage + rootfs.cpio.gz (ผู้เริ่มต้นภายนอก)

เมื่อฉันเริ่มใช้ qemu

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

หรือ

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

ฉันได้รับพฤติกรรมที่แตกต่างดังต่อไปนี้:

ด้วยรุ่น 2 (เริ่มต้นภายนอก) ทุกอย่างทำงานได้ดี "ยินดีต้อนรับ" จะปรากฏขึ้นและฉันได้รับพรอมต์ อย่างไรก็ตามด้วยเวอร์ชัน 1 (initramfs แบบฝัง) ฉันได้รับคำเตือน

unable to open an initial console

"ยินดีต้อนรับ" ไม่ปรากฏขึ้นและฉันได้รับพรอมต์ของฉัน

เท่าที่ฉันเข้าใจกระบวนการ initramfs ทั้งสองรุ่นควรมีไฟล์เดียวกันตั้งแต่ฉันสร้างมัน (หรือมีเคอร์เนลสร้าง) จากโฟลเดอร์ที่เหมือนกัน

ฉันสงสัยว่าใครสามารถช่วยฉันอธิบายเกี่ยวกับพฤติกรรมนี้ได้บ้าง

* อัพเดท *

ตามที่ mikeserv กล่าวไว้ในความคิดเห็นเคอร์เนลมีการเริ่มต้นฝังตัวน้อยที่สุดต่อค่าเริ่มต้น สิ่งนี้ยังคงปรากฏเมื่อใช้อุปกรณ์ภายนอก แต่จะถูกเขียนทับหากคุณฝังของคุณเอง ฉันพบว่าขัดกับข้อกำหนดนี้แน่นอนไม่ว่างเปล่า แต่มีโฟลเดอร์ dev, โฟลเดอร์รากและอุปกรณ์ / dev / console อุปกรณ์นี้จะถูกใช้เมื่อใช้ initramfs ภายนอก แต่จะถูกเขียนทับหากคุณฝังของคุณเอง ดังนั้นคุณต้องรวมอุปกรณ์ / dev / console ในแหล่ง initramfs ของคุณmknod -m 622 initramfs_src/dev/console c 5 1เมื่อทำการฝังของคุณเอง

ขอบคุณมากสำหรับ mikeserv, frostschutz และ JdeBP ที่ช่วยให้ฉันเข้าใจเรื่องนั้น!


สิ่งที่มีสิทธิ์ตั้งบน/dev/consoleในตัวของคุณ? ฉันคิดว่าความแตกต่างอาจเกี่ยวกับผู้ที่บรรจุในสองกรณี
mikeserv

คำถามที่คล้ายกันเป็นหลักสูตรstackoverflow.com/questions/10437995
JdeBP

@mikeserv อุปกรณ์คอนโซลมีสิทธิ์และความเป็นเจ้าของเหมือนกันในทั้งสองบิลด์
clw

@JdeBP ฉันไม่แน่ใจว่ามันคล้ายกันหรือเปล่าเพราะในทั้งสองกรณีฉันบูตให้รับพรอมต์และมีอุปกรณ์คอนโซล เฉพาะในการเริ่มต้นดำเนินการสะท้อนและอื่น ๆ ที่ไม่สามารถ
clw

1
การอนุญาตจะเหมือนกันใน initramfs อย่างไรถ้าคุณไม่ได้ใช้มันเลย?
mikeserv

คำตอบ:


2

พวกเขาเหมือนกันจริง ๆ ?

บิวด์อินที่คุณสามารถค้นหา/usr/src/linux/usr/initramfs_data.cpio.gzหรือแยกจาก bzImage ตามที่อธิบายไว้ที่นี่: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

หากคุณใช้บิวด์อินนั้นและใช้เป็นบิวด์ภายนอกแทนมันใช้งานได้หรือไม่

ถ้ามันยังคงแตกต่างกันเคอร์เนลจะเหมือนกันหรือไม่? (เปรียบเทียบ/proc/config.gzทั้งคู่)

ควรมีความแตกต่าง ฉันไม่ทราบว่าเคอร์เนลใส่ใจว่าต้นกำเนิดมาจากไหน ฉันสงสัยว่าจะqemuใช้การตั้งค่าที่แตกต่างกันเร็วๆ นี้เมื่อผ่าน-initrdพารามิเตอร์ ...

บน sidenote /initดูเหมือนว่ากระสุนของคุณจะวางกับฉัน ไม่ใช่setsid execฉันผิดหรือเปล่า?


1
คำตอบนี้ดูเหมือนจะเป็นคำถามทั้งหมด
JdeBP

1
@JdeBP: คุณไม่ได้คิดแบบสี่มิติ!
frostschutz

1
@frostschutz ขอบคุณมากสำหรับคำตอบของคุณ! เมื่อฉันใช้ initramfs ที่เคอร์เนลสร้าง (usr / initramfs_data.cpio.gz) เป็นส่วนภายนอกก็ใช้งานได้ดีเช่นกัน! นอกจากนี้เมื่อฉันจัดหาเคอร์เนลที่คอมไพล์ด้วย initramfs ฝังตัวกับภายนอกคำเตือนปรากฏขึ้นแม้ว่าภายนอกควรเขียนทับฝังตัว ( kernel.org/doc/Documentation/filesystems/ ...... ) ดังนั้นมันอาจจะไม่ใช่ qemu -initrd แต่มีบางอย่างภายในเคอร์เนลเอง ฉันไม่ได้เปลี่ยนอะไรอื่นแล้ว CONFIG_INITRAMFS_SOURCE แม้ว่า ..
clw

@frostschutz ตอบคำถามของคุณOn a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: วงวนเลียนแบบเก็ตตี้หรือเครื่องมือที่คล้ายกันนับตั้งแต่การเรียกshบล็อกจนกว่าเชลล์นั้นจะออก
stefanjunker

@stefanjunker และที่จะดียกเว้น setsid จะไม่ปิดกั้นเลย ...
frostschutz

1

คุณอาจสนใจว่า Buildroot 2018.02 จัดการกับสิ่งนี้อย่างไร

เมื่อใดก็ตามที่คุณใช้ initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y) หรือ initrd ( BR2_TARGET_ROOTFS_CPIO=n) จะเพิ่มสิ่งต่อไปนี้/initใน rootfs ของคุณ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 "$@"

การคัดลอกทำได้โดย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

นอกจากนี้ยังมีประโยชน์ที่จะทราบว่าพา ธ init มี/initไว้สำหรับ initramfs ซึ่งแตกต่างจาก/sbin/initอย่างอื่น: อะไรที่ทำให้การส่ง init = / path / to / program ไปยังเคอร์เนลไม่ได้เริ่มโปรแกรมในฐานะ init?

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.