Linux โหลดอิมเมจ 'initrd' อย่างไร


13

ฉันพยายามทำความเข้าใจกับกระบวนการบูท แต่มีเพียงสิ่งเดียวเท่านั้นที่จะข้ามหัวฉันได้ ..

ทันทีที่เคอร์เนล Linux ถูกบูทและติดตั้งระบบไฟล์รูท (/) โปรแกรมสามารถรันได้และโมดูลเคอร์เนลเพิ่มเติมสามารถรวมเข้าด้วยกันเพื่อให้มีฟังก์ชั่นเพิ่มเติม ในการเมาท์ระบบไฟล์รูทจะต้องปฏิบัติตามเงื่อนไขบางประการ เคอร์เนลต้องการไดรเวอร์ที่เกี่ยวข้องเพื่อเข้าถึงอุปกรณ์ที่ระบบไฟล์รูทอยู่ (โดยเฉพาะไดรเวอร์ SCSI) เคอร์เนลจะต้องมีรหัสที่จำเป็นในการอ่านระบบไฟล์ (ext2, reiserfs, romfs, ฯลฯ ) เป็นไปได้ว่าระบบไฟล์รูทถูกเข้ารหัสอยู่แล้ว ในกรณีนี้จำเป็นต้องใช้รหัสผ่านเพื่อต่อเชื่อมระบบไฟล์

ramdisk เริ่มต้น (หรือที่เรียกว่า initdisk หรือ initrd) แก้ปัญหาได้อย่างแม่นยำตามที่อธิบายไว้ข้างต้น เคอร์เนล Linux จัดให้มีตัวเลือกในการโหลดระบบไฟล์ขนาดเล็กลงในดิสก์ RAM และใช้งานโปรแกรมก่อนที่จะติดตั้งระบบไฟล์รูทจริง การโหลดของ initrd ได้รับการจัดการโดย boot loader (GRUB, LILO และอื่น ๆ ) ตัวโหลดการบูตต้องการรูทีน BIOS เท่านั้นเพื่อโหลดข้อมูลจากสื่อการบูต หากบูตโหลดเดอร์สามารถโหลดเคอร์เนลได้ก็สามารถโหลด ramdisk เริ่มต้นได้ ไม่จำเป็นต้องใช้ไดรเวอร์พิเศษ

หาก / boot ไม่ใช่พาร์ติชันที่แตกต่างกัน แต่มีอยู่ใน / partition ดังนั้นตัวโหลดบูตไม่จำเป็นต้องใช้ไดรเวอร์ SCSI เพื่อเข้าถึงอิมเมจ 'initrd' และอิมเมจเคอร์เนลหรือไม่ หากคุณสามารถเข้าถึงภาพโดยตรงแล้วทำไมเราต้องใช้ไดรเวอร์ SCSI

คำตอบ:


20

Nighpher ผมจะพยายามที่จะตอบคำถามของคุณ แต่สำหรับคำอธิบายที่ครอบคลุมมากขึ้นของกระบวนการบูตลองบทความไอบีเอ็ม

ตกลงฉันคิดว่าคุณกำลังใช้ GRUB หรือ GRUB2 เป็น bootloader ของคุณสำหรับคำอธิบาย ก่อนอื่นเมื่อ BIOS เข้าถึงดิสก์ของคุณเพื่อโหลด bootloader มันจะใช้รูทีนในตัวสำหรับการเข้าถึงดิสก์ซึ่งถูกเก็บไว้ใน 13h interrupt ที่มีชื่อเสียง Bootloader (และเคอร์เนลในขั้นตอนการตั้งค่า) ใช้ประโยชน์จากรูทีนเหล่านั้นเมื่อเข้าถึงดิสก์ โปรดทราบว่า BIOS ทำงานในโหมดจริง (16 บิต) ของโปรเซสเซอร์ดังนั้นจึงไม่สามารถระบุ RAM ได้มากกว่า 2 ^ 20 ไบต์ (2 ^ 20 ไม่ใช่ 2 ^ 16 เพราะแต่ละแอดเดรสในโหมดจริงประกอบด้วย Segment_address * 16 + ออฟเซ็ต ที่ทั้งอยู่เซ็กเมนต์และชดเชยเป็น 16 บิตดูhttp://en.wikipedia.org/wiki/X86_memory_segmentation ) ดังนั้นกิจวัตรเหล่านี้ไม่สามารถเข้าถึง RAM มากกว่า 1 MiB ซึ่งเป็นข้อ จำกัด ที่เข้มงวดและความไม่สะดวกที่สำคัญ

BIOS โหลดรหัส bootloader จาก MBR - 512 ไบต์แรกของดิสก์ของคุณและเรียกใช้งาน หากคุณกำลังใช้ GRUB รหัสนั้นจะเป็น GRUB ขั้นที่ 1 โค้ดนั้นจะโหลด GRUB สเตจ 1.5 ซึ่งอยู่ในพื้นที่ดิสก์ 32 กิโลบิตแรกซึ่งเรียกว่าภูมิภาคเข้ากันได้ของ DOS หรือจากที่อยู่ถาวรของระบบไฟล์ ไม่จำเป็นต้องทำความเข้าใจกับระบบไฟล์เพื่อทำสิ่งนี้เพราะเหตุนี้ถึงแม้ว่าขั้นตอนที่ 1.5 จะอยู่ในระบบไฟล์มันเป็นรหัส "ดิบ" และสามารถโหลดไปยัง RAM โดยตรงและดำเนินการได้ที่: http://www.pixelbeat.org/ เอกสาร / ดิสก์ / โหลดของ stage1.5 จากดิสก์ไปยัง RAM ทำให้การใช้รูทีนการเข้าถึงดิสก์ BIOS

ป้อนคำอธิบายรูปภาพที่นี่

Stage1.5 มียูทิลิตีระบบไฟล์เพื่อให้สามารถอ่านสเตจ 2 จากระบบไฟล์ได้ (ยังคงใช้ BIOS 13h เพื่ออ่านจากดิสก์ถึง RAM แต่ตอนนี้มันสามารถถอดรหัสข้อมูลระบบไฟล์เกี่ยวกับ inodes ฯลฯ และรับรหัสดิบจาก ดิสก์). BIOS ที่เก่ากว่าอาจไม่สามารถเข้าถึง HD ทั้งหมดได้เนื่องจากข้อ จำกัด ในโหมดการกำหนดแอดเดรสของดิสก์ - พวกเขาอาจใช้ระบบ Cylinder-Head-Sector ไม่สามารถจัดการกับพื้นที่ดิสก์ได้มากกว่า 8 GiB แรก: http: //en.wikipedia org

Stage2 โหลดเคอร์เนลเป็น RAM (อีกครั้งโดยใช้ยูทิลิตี้ดิสก์ BIOS) หากเป็นเคอร์เนล 2.6+ เคอร์เนลก็มีการรวบรวม initramfs ไว้ภายในดังนั้นจึงไม่จำเป็นต้องโหลด หากเป็นเคอร์เนลที่เก่ากว่า bootloader จะโหลดอิมเมจ initrd แบบสแตนด์อโลนไว้ในหน่วยความจำด้วยดังนั้นเคอร์เนลจึงสามารถเมานต์และรับไดรเวอร์สำหรับติดตั้งระบบไฟล์จริงจากดิสก์

ปัญหาคือเคอร์เนล (และ ramdisk) มีน้ำหนักมากกว่า 1 MiB ดังนั้นการโหลดลงใน RAM คุณต้องโหลดเคอร์เนลเป็น 1 MiB แรกจากนั้นข้ามไปที่โหมดป้องกัน (32 บิต) ย้ายเคอร์เนลที่โหลดไปยังหน่วยความจำสูง (ฟรี 1 MiB แรกสำหรับโหมดจริง) จากนั้นกลับสู่โหมดจริง (16 บิต) อีกครั้งรับ ramdisk จากดิสก์ไปที่ 1 MiB แรก (ถ้าเป็นโหมด initrd และเคอร์เนลที่แยกต่างหาก) อาจเปลี่ยนเป็นโหมดป้องกัน (32 บิต) อีกครั้ง นำไปไว้ในตำแหน่งที่เป็นไปได้กลับไปที่โหมดจริง (หรือไม่: /programming/4821911/does-grub-switch-to-protected-mode ) และรันโค้ดเคอร์เนล คำเตือน: ฉันไม่แน่ใจเกี่ยวกับความละเอียดและความแม่นยำของคำอธิบายส่วนนี้ทั้งหมด

ตอนนี้เมื่อคุณรันเคอร์เนลในที่สุดคุณก็มีมันและ ramdisk ถูกโหลดเข้าไปใน RAM โดย bootloaderดังนั้นเคอร์เนลจึงสามารถใช้ยูทิลิตี้ดิสก์จาก ramdisk เพื่อติดตั้งระบบไฟล์รูทจริงและเดือยหลักของมัน มีไดรเวอร์ ramfs อยู่ในเคอร์เนลดังนั้นจึงสามารถเข้าใจเนื้อหาของ initramfs ได้


bootlader ไม่สามารถโหลดเคอร์เนลเป็นชิ้น ๆ แทนที่จะกระโดดเข้าสู่โหมดป้องกันได้หรือไม่? และสิ่งที่จำเป็นสำหรับการปลดปล่อยที่ 1 MB .. (ขออภัย .. ไม่เข้าใจว่า .. )
rpthms

ความต้องการในการปลดปล่อย 1MiB แรกนั้นมีดังนี้: bootloader สามารถเข้าถึงฮาร์ดไดรฟ์ของคุณได้ในโหมดจริงเท่านั้นเพราะมันเข้าถึงด้วยยูทิลิตี้ไบออสซึ่งเป็นโหมดจริง โหมดจริงไม่เห็น RAM ใด ๆ ยกเว้น 1 MiB แรก แต่คุณต้องโหลดเคอร์เนล + initramfs ลงใน RAM และใช้พื้นที่ ~ 5 MiB ใน RAM ยูทิลิตี้ไบออสเหล่านั้นจะไม่สามารถบีบ 5 MiB เป็น 1 MiB แรก ดังนั้น bootloader จะต้องคัดลอกจากดิสก์ไปที่ 1 MiB แรกจากนั้นไปที่โหมดป้องกันและย้ายจาก RAM 1Mb แรกไปยัง RAM ที่สูงกว่า ตอนนี้ชัดเจนขึ้นหรือไม่ :)
Boris Burkov

1
เนื้อหาทั้งหมดในช่วง 1 / 1.5 / 2 เป็นด้วงมรดก
psusi

1
@CMCDragonkai ใช่ด่าน 2 bootloader อยู่ในระบบแฟ้ม (กล่าวคือใน/bootพาร์ทิชัน) เคอร์เนลไม่ได้รับการโหลด ณ จุดนี้ - เป็นด้วงของ 1.5 ซึ่งกำลังเข้าถึงสเตจ 2 ใน/bootระบบไฟล์ (เช่นใน/boot/grubไฟล์) ผ่านไดรเวอร์ระบบไฟล์ที่เรียบง่าย เคอร์เนลจะสามารถอ่านได้จาก/bootพาร์ติชัน แต่จะเกิดขึ้นในภายหลังหลังจากการเรียกใช้โค้ด grub2 และโหลดเคอร์เนลและหลังจากเคอร์เนลอ่าน initramfs คุณกำลังพูดinit.shถึง initramfs หรือไม่? มันอยู่ใน/bootพาร์ติชั่นฮาร์ดไดรฟ์ของคุณจากนั้นสเตจ 2 ของด้วงจะใส่ลงใน RAM และเคอร์เนลจะอ่านจากแรม
Boris Burkov

1
initrd ต้องเป็นไฟล์แยกต่างหาก initramfs ที่ใหม่กว่าสามารถเชื่อมโยงกับเคอร์เนล แต่ไม่จำเป็นต้องเป็น - มันยังสามารถโหลดเป็นไฟล์แยกต่างหากโดย bootloader เนื่องจากไฟล์ initramfs ถูกกำหนดเป็นลำดับของไฟล์เก็บถาวร cpio bootloaders บางตัว (เช่น iPXE) จึงอนุญาตให้ใช้ไฟล์ initramfs หลายไฟล์ซึ่งจะโหลดลงในหน่วยความจำทีละไฟล์ นอกจากนี้ลีนุกซ์รุ่นดิสทริบิวชั่นบางตัวใช้ชื่อไฟล์แบบเริ่มต้นสำหรับความเข้ากันได้แบบย้อนหลังแม้ว่าเทคโนโลยีจริงที่ใช้ตอนนี้คือ initramfs
telcoM

1

ฉันเชื่อว่ามันจะเพิ่มความสามารถให้กับคุณสมบัติพิเศษที่ bootloader สนับสนุน เช่น. ไม่จำเป็นต้องรู้ระบบไฟล์เฉพาะของพาร์ติชั่นรวม (boot + root) ในกรณีนี้คุณเพียงแค่สร้างพาร์ติชันสำหรับบูตแยกต่างหากโดยที่มันสามารถทำงานร่วมกับ bootloader ของคุณและความซับซ้อนอื่น ๆ ของวิธีการเมาท์พาร์ติชั่นรูทของคุณจะถูกทิ้งไว้ในเคอร์เนลและอิมเมจเริ่มระบบจากบูตพาร์ติชัน Bootloader รู้วิธีเข้าถึงอุปกรณ์ SCSI (และอุปกรณ์อื่น ๆ เช่นกันโดยขึ้นอยู่กับการใช้ bootloader) ด้วยการใช้ไดรเวอร์ของตัวเองหรือโดยการใช้ BIOS ประจำ ยิ่งไปกว่านั้นมันรู้วิธีการอ่านระบบไฟล์บางอย่าง ฯลฯ

พิจารณาเช่น วิธีการ UEFI ของการบูทซึ่งเฟิร์มแวร์ UEFI รู้วิธีเข้าถึงพาร์ติชัน EFI อยู่แล้วให้อ่านและโหลดเคอร์เนล linux จากที่นั่นโดยไม่ต้องใช้ bootloader ระดับกลาง ในกรณีนี้ภาพ linux จะถูกแยกออกจากพาร์ติชั่นรูทและเฟิร์มแวร์ UEFI ไม่จำเป็นต้องรู้ระบบไฟล์ที่แปลกใหม่ทั้งหมดในการเข้าถึง ฉันเชื่อว่าการแยกอิมเมจ "บูต" ออกจากพาร์ทิชัน "รูท" เป็นเรื่องที่สมเหตุสมผล หากไม่ใช่เพื่อสิ่งอื่นสิ่งนี้เป็นสิ่งจำเป็นเมื่อตั้งค่าการเข้ารหัสระบบไฟล์รูท


0

เพียงบันทึกถ้า bootloader ไม่โหลด initrd มันคุ้มค่าที่จะทดสอบ bootloader อื่น ฉันเพิ่งพบเจอสถานการณ์เช่นนี้เมื่อ LILO เพิกเฉยต่อการเริ่มต้นขนาดกลางที่ระบุไว้อย่างถูกต้อง (<4Mb; extfs rootfs เดียวบน SATA SSD; GPT) และ GRUB 2.00

กระบวนการบูตจบลงอย่างรวดเร็วด้วยวิธีทั่วไป

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.