Come fa un kernel a montare la partizione di root?


29

La mia domanda riguarda l'avvio di un sistema Linux da una partizione separata / boot. Se la maggior parte dei file di configurazione si trova su una partizione / separata, come fa il kernel a montarlo correttamente all'avvio?

Qualsiasi elaborazione su questo sarebbe grandiosa. Sento che mi manca qualcosa di essenziale. Mi occupo principalmente del processo e dell'ordine delle operazioni.

Grazie!

EDIT: Penso che ciò che dovevo chiedere fosse più lungo le linee del file dev che viene usato nel parametro del kernel root. Ad esempio, supponiamo di dare il mio parametro root come root = / dev / sda2. In che modo il kernel ha una mappatura del file / dev / sda2?


Sebbene le persone sottostanti coprano initrd, ci sono poche discussioni sul perché viene utilizzato initrd. La mia impressione è che le distribuzioni come Debian vogliono usare un kernel su molte macchine diverse della stessa architettura, ma probabilmente hardware ampiamente diverso. Ciò è reso possibile dalla modularizzazione del supporto hardware tramite moduli del kernel. Initrd non richiede molto supporto hardware per l'avvio e, una volta fatto, carica i moduli hardware necessari per procedere. Elaborazioni / correzioni a questo sono apprezzate.
Faheem Mitha,

Non è possibile montare / boot senza avere / montato prima, poiché non esiste una directory / boot senza /.
psusi,

Risposte:


20

Inizialmente Linux si avvia con un ramdisk (chiamato un initrd, per "INITial RamDisk") come /. Questo disco ha abbastanza su di esso per essere in grado di trovare la vera partizione di root (inclusi eventuali moduli driver e filesystem richiesti). Monta la partizione di root su un punto di montaggio temporaneo su initrd, quindi invoca pivot_root(8)per scambiare i punti di montaggio temporaneo e root, lasciando initrdin posizione per essere umounteditato e il vero filesystem di root attivo /.


2
E se non avessi un initrd come LFS (linuxfromscratch.org)?
Mr. Shickadance,

@Sig. Shickadance: Non avendo esaminato il modo in cui LFS fa le cose, immagino che si assicurino che il kernel abbia tutti i moduli necessari compilati (o caricati tramite GRUB 2, la cui possibilità è abbastanza nuova da non essere stata notata da molte distribuzioni), quindi può iniziare sulla partizione root effettiva.
Geekosaur,

4
@Sig. Shickadance. Non è solo LFS che non ha un initrd. Chiunque compili il proprio kernel ha la possibilità di non usare un initrd, cosa che faccio su Gentoo.
jonescb,

1
@Faheem: i moduli grub2 non sono gli stessi dei moduli del kernel. Vedo una certa capacità per grub2 di caricare i moduli del kernel, ma una cosa che non so è se funzionerà per il kernel Linux o solo per * BSD (dove il bootloader che carica i moduli del kernel è normale). Sospetto che al kernel debba essere insegnato dove trovare la mappa degli indirizzi per i moduli caricati, e tutti devono passare a grub2 (grub1 è ancora standard in alcune distribuzioni).
Geekosaur,

1
Initrd è stato sostituito da initramfs, poiché pivot_root è stato considerato un hack sporco.
psusi,

41

Nei tempi antichi, il kernel era codificato per conoscere il numero maggiore / minore del dispositivo dei root fs e montava quel dispositivo dopo aver inizializzato tutti i driver di dispositivo, che erano integrati nel kernel. L' rdevutilità potrebbe essere utilizzata per modificare il numero del dispositivo radice nell'immagine del kernel senza doverlo ricompilare.

Alla fine è arrivato il boot loader e potrebbe passare una riga di comando al kernel. Se l' root=argomento è stato passato, ciò indicava al kernel dove si trovava la radice fs anziché il valore incorporato. I driver dovevano accedere a quelli che dovevano ancora essere integrati nel kernel. Mentre l'argomento sembra un normale nodo del dispositivo nella /devdirectory, ovviamente non esiste alcuna /devdirectory prima che il root fs sia montato, quindi il kernel non può cercare un nodo dev lì. Invece, alcuni nomi di dispositivi ben noti sono codificati nel kernel in modo che la stringa possa essere tradotta nel numero di dispositivo. Per questo motivo, il kernel può riconoscere cose come /dev/sda1, ma non cose più esotiche /dev/mapper/vg0-rooto un UUID di volume.

Più tardi, è initrdentrato in scena. Insieme al kernel, il boot loader caricava l' initrdimmagine, che era una specie di immagine del filesystem compresso (immagine ext2 gzipped, immagine rom rom gzipped, gli squashfs alla fine diventavano dominanti). Il kernel decomprimerebbe questa immagine in un ramdisk e monterebbe il ramdisk come root fs. Questa immagine conteneva alcuni driver aggiuntivi e script di avvio invece che reali init. Questi script di avvio hanno eseguito varie attività per riconoscere l'hardware, attivare elementi come array di raid e LVM, rilevare UUID e analizzare la riga di comando del kernel per trovare la radice reale, che ora potrebbe essere specificata da UUID, etichetta del volume e altre cose avanzate. Quindi ha montato il vero root fs /initrd, quindi ha eseguito la pivot_rootchiamata di sistema per far scambiare il kernel /e/initrd, quindi esegui /sbin/initsulla radice reale, che smonterebbe /initrde libererebbe il ramdisk.

Finalmente, oggi abbiamo il initramfs. Questo è simile al initrd, ma invece di essere un'immagine di filesystem compresso che viene caricata in un ramdisk, è un archivio compresso cpio. Un tmpfs viene montato come root e l'archivio viene estratto lì. Invece di usare pivot_root, che era considerato un trucco sporco, gli initramfsscript di avvio montano la radice reale dentro /root, eliminano tutti i file nella radice tmpfs, quindi chrootin /root, ed exec /sbin/init.


1
Dopo il chroot, i tmpfs vengono automaticamente smontati? Scompare e basta?
jiggunjer,

@jiggunjer, no, è ancora lì, è solo vuoto (oltre a contenere la directory / root), e non viene più utilizzato.
psusi,

Ho imparato qualcosa di nuovo su ogni iterazione di root fs che hai citato. Bella risposta!
jpaugh

3

Sembra che tu stia chiedendo come fa il kernel a "sapere" quale partizione è la partizione root, senza accesso ai file di configurazione su / etc.

Il kernel può accettare argomenti da riga di comando come qualsiasi altro programma. GRUB o la maggior parte degli altri bootloader possono accettare argomenti della riga di comando come input dell'utente o archiviarli e rendere disponibili varie combinazioni di argomenti della riga di comando tramite un menu. Il bootloader passa gli argomenti della riga di comando al kernel quando lo carica (non conosco il nome o la meccanica di questa convenzione ma è probabilmente simile a come un'applicazione riceve argomenti della riga di comando da un processo chiamante in un kernel in esecuzione).

Una di quelle opzioni della riga di comando è root, dove è possibile specificare il filesystem di root, ad es root=/dev/sda1.

Se il kernel usa un initrd, il bootloader è responsabile di dire al kernel dove si trova o di mettere initrd in una posizione di memoria standard (penso) - questo è almeno il modo in cui funziona sul mio Guruplug.

È del tutto impossibile non specificarne uno e quindi avere il panico del kernel immediatamente dopo aver iniziato a lamentarsi che non riesce a trovare un filesystem di root.

Potrebbero esserci altri modi per passare questa opzione al kernel.


3
Questa è la spiegazione giusta quando non c'è initrd / initramfs, ma manca un pezzo del puzzle. Normalmente il kernel identifica un dispositivo come /dev/sda1perché è una voce in un filesystem. Si potrebbe fare cp -p /dev/sda1 /tmp/fooe /tmp/foorappresenterebbe lo stesso dispositivo. Sulla riga comandi del kernel, il kernel utilizza un parser incorporato che segue la consueta convenzione di denominazione dei dispositivi: sda1indica la prima partizione del primo disco simile a SCSI.
Gilles 'SO- smetti di essere malvagio' il

@Gilles così i kernel moderni non riescono ancora a montare un volume basato sull'UUID? senza initrdo initramfsintendo. Deve essere una partizione "semplice" nel /dev/sdxmodulo?
jiggunjer,

1
@jiggunjer I kernel moderni supportano la ricerca di un volume tramite UUID. Vedere init/do_mounts.c.
Gilles 'SO- smetti di essere malvagio' il

1

Grub monta la /bootpartizione e quindi esegue il kernel. Nella configurazione di Grub, dice al kernel cosa usare come dispositivo root.

Ad esempio in Grub menu.lst:

kernel /boot/linux root=/dev/sda2

1

Dai, GRUB non "monta" / avvia, legge solo "menu.lst" e alcuni moduli, non fa neanche parte del kernel LINUX. Quando chiami il kernel, passerai un argomento "root" con la partizione root. Nel peggiore dei casi, il kernel sa che è stato montato just / boot (LOL).

Next: geekosaur ha ragione, Linux usa un ramdisk iniziale in formato di immagine compresso, quindi monta il vero filesystem di root chiamando pivot_root. Quindi Linux inizia a funzionare da un'immagine e quindi dall'unità disco locale.


1
Grub ha sicuramente la possibilità di "montare" un filesystem, specialmente in grub2. Ovviamente, tutto ciò che è in grado / fare / con esso è cercare kernel avviabili di una striscia o di un'altra, ma è ancora in fase di montaggio. Inoltre, Linux non richiede un initrd a meno che il kernel non abbia compilato i driver cruciali per il disco rigido come moduli.
Shadur,

5
ibm.com/developerworks/linux/library/l-linuxboot Questo è un riassunto abbastanza conciso di ciò che fa il kernel Linux all'avvio.
jsbillings,

2
@Shadur, dalla manpage mount : Tutti i file accessibili in un sistema Unix sono disposti in un grande albero, la gerarchia dei file, radicata in /. Questi file possono essere distribuiti su più dispositivi. Il comando mount serve per collegare il file system trovato su alcuni dispositivi all'albero dei file di grandi dimensioni. - Dato che i filesystem utilizzati da GRUB non sono collegati alla gerarchia dei file, NON si sta montando .
D4RIO,

1
@Shadur, BTW: È ovvio che initrd non è necessario dato che è solo un altro filesystem di root, ma è generalmente usato come root di avvio piccolo, poiché il kernel carica il necessario per l'avvio, quindi si avvia e infine carica tutto il resto.
D4RIO,

1
@ d4rio Sono montati da GRUB, non da Linux - diventa più facile da capire se si considera grub come un sistema operativo microkernel piuttosto che un semplice bootloader.
Shadur,

1

Il boot loader, sia esso grub o lilo o altro, dice al kernel dove guardare con il root=flag e opzionalmente carica un ramdisk iniziale in memoria tramite initrdprima di avviare il kernel.

Il kernel quindi carica, testa i suoi driver hardware e dispositivo e cerca nel sistema ciò che può vedere (puoi rivedere queste informazioni diagnostiche digitando dmesg; al giorno d'oggi probabilmente scorre troppo velocemente per vedere) quindi tenta di montare la partizione menzionata in il root=parametro

Se è presente un initrd, viene montato per primo e tutti i moduli / driver di dispositivo su di esso vengono caricati e analizzati prima del montaggio del filesystem di root. In questo modo è possibile compilare i driver per i dischi rigidi come moduli ed essere ancora in grado di avviarsi.

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.