In che modo Linux carica l'immagine 'initrd'?


13

Ho cercato di capire il processo di avvio, ma c'è solo una cosa che mi sta passando per la testa ...

Non appena il kernel Linux è stato avviato e montato il file system radice (/), i programmi possono essere eseguiti e ulteriori moduli del kernel possono essere integrati per fornire funzioni aggiuntive. Per montare il file system di root, devono essere soddisfatte determinate condizioni. Il kernel ha bisogno dei driver corrispondenti per accedere al dispositivo su cui si trova il file system radice (in particolare i driver SCSI). Il kernel deve inoltre contenere il codice necessario per leggere il file system (ext2, reiserfs, romfs, ecc.). È anche ipotizzabile che il file system di root sia già crittografato. In questo caso, è necessaria una password per montare il file system.

Il ramdisk iniziale (chiamato anche initdisk o initrd) risolve esattamente i problemi sopra descritti. Il kernel di Linux offre la possibilità di caricare un piccolo file system su un disco RAM e di eseguire i programmi lì prima che venga montato il file system radice effettivo. Il caricamento di initrd è gestito dal boot loader (GRUB, LILO, ecc.). I boot loader necessitano solo di routine BIOS per caricare i dati dal supporto di avvio. Se il boot loader è in grado di caricare il kernel, può anche caricare il ramdisk iniziale. Non sono richiesti driver speciali.

Se / boot non è una partizione diversa, ma è presente nella partizione /, il boot loader non dovrebbe richiedere i driver SCSI, per accedere all'immagine "initrd" e all'immagine del kernel? Se puoi accedere direttamente alle immagini, allora perché abbiamo esattamente bisogno dei driver SCSI ??

Risposte:


20

Nighpher, proverò a rispondere alla tua domanda, ma per una descrizione più completa del processo di avvio, prova l' articolo IBM .

Ok, presumo che tu stia usando GRUB o GRUB2 come bootloader per spiegazioni. Prima di tutto, quando il BIOS accede al tuo disco per caricare il bootloader, utilizza le sue routine integrate per l'accesso al disco, che sono archiviate nel famoso interrupt 13h. Bootloader (e kernel in fase di installazione) utilizzano queste routine quando accedono al disco. Si noti che il BIOS funziona in modalità real (16 bit) in modalità processore, quindi non può indirizzare più di 2 ^ 20 byte di RAM (2 ^ 20 non 2 ^ 16 perché ogni indirizzo in modalità reale comprende segment_address * 16 + offset , dove sia l'indirizzo del segmento che l'offset sono a 16 bit, consultare http://en.wikipedia.org/wiki/X86_memory_segmentation ). Pertanto, queste routine non possono accedere a più di 1 MiB di RAM, il che costituisce una limitazione rigorosa e un grave inconveniente.

Il BIOS carica il codice del bootloader direttamente dall'MBR: i primi 512 byte del disco e lo esegue. Se stai usando GRUB, quel codice è GRUB fase 1. Quel codice carica GRUB fase 1.5, che si trova nei primi 32 KiB di spazio su disco, chiamato regione di compatibilità DOS o da un indirizzo fisso del file system. Non ha bisogno di capire il file system per farlo, perché anche lo stadio 1.5 è nel file system, è un codice "raw" e può essere caricato direttamente nella RAM ed eseguito: http://www.pixelbeat.org/ docs / disk / . Il caricamento di stage1.5 dal disco alla RAM utilizza le routine di accesso al disco del BIOS.

inserisci qui la descrizione dell'immagine

Stage1.5 contiene le utilità del filesystem, in modo che possa leggere stage2 dal filesystem (beh, usa ancora BIOS 13h per leggere da disco a RAM, ma ora può decifrare le informazioni del filesystem sugli inode ecc. E ottenere il codice raw dal disco). I BIOS più vecchi potrebbero non essere in grado di accedere a tutto l'HD a causa delle limitazioni nella loro modalità di indirizzamento del disco: potrebbero utilizzare il sistema Cylinder-Head-Sector, incapace di occupare più dei primi 8 GiB di spazio su disco: http: //en.wikipedia. org / wiki / settore testa-cilindro .

Stage2 carica il kernel nella RAM (di nuovo, usando le utilità del disco BIOS). Se è un kernel 2.6+, ha anche initramfs compilato all'interno, quindi non è necessario caricarlo. Se è un kernel più vecchio, bootloader carica anche l'immagine initrd autonoma in memoria, in modo che il kernel possa montarla e ottenere i driver per il montaggio del file system reale dal disco.

Il problema è che il kernel (e il ramdisk) pesano più di 1 MiB, quindi per caricarli nella RAM devi caricare il kernel nel primo 1 MiB, quindi passare alla modalità protetta (32 bit), spostare il kernel caricato in memoria alta (libero il primo 1 MiB per la modalità reale), quindi tornare nuovamente alla modalità reale (16 bit), ottenere ramdisk dal disco al primo 1 MiB (se si tratta di un initrd separato e di un kernel precedente), possibilmente passare nuovamente alla modalità protetta (32 bit), mettilo dove appartiene, eventualmente torna alla modalità reale (o no: /programming/4821911/does-grub-switch-to-protected-mode ) ed esegui il codice del kernel. Avvertenza: non sono del tutto sicuro della completezza e accuratezza di questa parte della descrizione.

Ora, quando finalmente esegui il kernel, lo hai già caricato e ramdisk caricato nella RAM dal bootloader , quindi il kernel può usare le utilità del disco da ramdisk per montare il tuo vero file system root e pivot root su di esso. I driver ramfs sono presenti nel kernel, quindi può comprendere il contenuto di initramfs, ovviamente.


Il bootlader non può semplicemente caricare il kernel in blocchi, invece di saltare in modalità protetta ?? E qual è la necessità di liberare quel 1 MB .. (Siamo spiacenti .. non riuscivo a capirlo ..)
rpthms

La necessità di liberare il primo 1MiB è la seguente: il bootloader può accedere al tuo disco rigido solo in modalità reale, perché accede ad esso con utility BIOS, che sono in modalità reale (funzionano su argomenti a 16 bit e utilizzano operazioni a 16 bit). La modalità reale non vede RAM, tranne che per il primo 1 MiB. Ma devi caricare kernel + initramfs nella RAM e occupano ~ 5 MiB di spazio nella RAM. Quelle utility del BIOS non saranno in grado di spremere 5 MiB nel primo 1 MiB. Quindi, il bootloader deve copiarli dal disco al primo 1 MiB, quindi passare alla modalità protetta e spostarli dalla prima RAM da 1 MB a RAM superiore. Adesso è più chiaro? :)
Boris Burkov,

1
L'intera fase 1 / 1.5 / 2 è roba da eredità.
psusi,

1
@CMCDragonkai Sì, il bootloader stage2 si trova nel filesystem (ovvero nella /bootpartizione). Il kernel non è caricato a questo punto - è stage1.5 di grub, che accede a stage2 nel /bootfilesystem (ad esempio nel /boot/grubfile) tramite i suoi driver minimalisti del filesystem. Il kernel sarà anche in grado di leggere dalla /bootpartizione, ma accadrà in seguito, dopo l'esecuzione del codice grub2 e il caricamento del kernel e dopo che il kernel legge initramfs. Stai parlando degli init.shinitramfs? Risiede nella /bootpartizione del disco rigido, quindi stage2 di grub lo mette nella RAM e Kernel lo legge dalla RAM.
Boris Burkov il

1
Initrd doveva essere un file separato. I nuovi initramfs possono essere collegati al kernel, ma non è necessario : può anche essere caricato come file separato dal bootloader. Poiché il file initramfs è definito come una sequenza di archivi cpio, alcuni bootloader (ad es. IPXE) consentono persino più file initramfs, che verranno caricati in memoria uno dopo l'altro. Inoltre, alcune distribuzioni Linux utilizzano nomi di file in stile initrd per la compatibilità con le versioni precedenti, sebbene la tecnologia utilizzata attualmente sia initramfs.
telcoM

1

Credo, si riduce a ciò che supporta particolari bootloader. Per esempio. non deve conoscere un particolare filesystem della tua partizione combinata (boot + root). In tal caso, basta creare una partizione di avvio separata a condizione che funzioni con il proprio bootloader e qualsiasi altra complessità su come montare la partizione di root viene lasciata sul kernel e l'immagine di avvio avviata dalla partizione di avvio. Bootloader sa come accedere ai dispositivi SCSI (e anche ad altri dispositivi, a seconda del bootloader utilizzato) utilizzando i propri driver o utilizzando le routine del BIOS. Inoltre, sa leggere alcuni filesystem, ecc.

Considerare ad es. Modalità di avvio UEFI, in cui il firmware UEFI già sa come accedere alla partizione EFI, leggerlo e caricare il kernel Linux da lì senza la necessità di un bootloader intermedio. In quel caso l'immagine di Linux vive separata dalla partizione di root e il firmware UEFI non deve conoscere tutti i filesystem esotici per accedervi. Credo che la separazione delle immagini "boot" dalla partizione "root" abbia molto senso. Se non altro, questa è una necessità quando si configura la crittografia del filesystem di root.


0

Per la cronaca, se un bootloader non carica initrd vale la pena testare un altro bootloader; Mi sono appena imbattuto in una situazione come questa quando LILO ha ignorato silenziosamente un initrd correttamente specificato di medie dimensioni (<4Mb; rootfs ext4 singoli su un SSD SATA; GPT) e GRUB 2.00 è riuscito.

Il processo di avvio si è concluso rapidamente con un tipico

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.