Repository 32bit  Forum
Repository 64bit  Wiki

Slackware Linux initrd HOWTO: differenze tra le versioni

Da Slacky.eu.
m (mkinitrd)
m (Nozioni di Base)
 
(Una revisione intermedia di un utente non mostrate)
Riga 77: Riga 77:
'''3.2) esecuzione di uno pseudo-init presente all'interno dell'initrd'''
'''3.2) esecuzione di uno pseudo-init presente all'interno dell'initrd'''
'''3.3) montaggio del reale root filesystem'''
'''3.3) montaggio del reale root filesystem'''
4) caricamento di init dal filesystem root da parte del kernel, con conseguente inizializzazione del sistema
+
4) caricamento di init dal filesystem root ''da parte dello pseudo-init dell'initrd'', con conseguente inizializzazione del sistema
A questo punto, dovrebbe essere chiaro lo scopo dell'avere un initrd image e la sua collocazione nel sistema GNU/Linux. Come fare quindi per creare e gestire un initrd image?
A questo punto, dovrebbe essere chiaro lo scopo dell'avere un initrd image e la sua collocazione nel sistema GNU/Linux. Come fare quindi per creare e gestire un initrd image?

Versione attuale delle 14:02, 23 apr 2008

Indice

[modifica] Disclaimer

L'autore di questa guida, i suoi collaboratori e slacky.eu non si riterranno responsabili di eventuali danni provocati al vostro computer.

[modifica] Prerequisiti

Questa guida usa come riferimento la distribuzione Slackware GNU/Linux 12.0. I principi in essa esposti comunque sono applicabili a qualsiasi distribuzione GNU/Linux. Il tool principale utilizzato nel corso della wiki, mkinitrd, rimane comunque una prerogativa di Slackware Linux.

Ovviamente, per poter avere successo nell'operazione, è necessario avere una buona conoscenza della distribuzione, una buona padronanza dei comandi di base ed, in alcuni casi, della procedura di configurazione e compilazione del Kernel. Per quanto riguarda Slackware, consultare la pagina Compilazione e ricompilazione Kernel su Slackware di questa stessa Wiki.

Si consiglia caldamente:

  • di stampare la guida prima di procedere al suo utilizzo. In questo modo, se modificando il kernel o lilo si dovessero commettere degli errori, si potrà comunque avere accesso alle informazioni utili a recuperare l'utilizzo del sistema.
  • di conservare sempre un kernel configurato e funzionante, aggiungendo il kernel modificato (nel caso sia necessario) come kernel aggiuntivo ed opzionale, per lo stesso motivo di cui sopra.

Nel corso di questa guida, verranno modificati una serie di file configurazione spesso vitali per l'utilizzo della propria distribuzione, per questo motivo, è cosa saggia effettuare una copia di backup di ognuno di questi file.

Nello specifico, modificheremo:

  • il kernel
cp /usr/src/linux/.config /home/home_utente/config.backup
  • il file di configurazione di lilo
cp /etc/lilo.conf /home/home_utente/lilo.conf.backup
  • i sorgenti dell'initrd
cp -Rp /boot/initrd-tree /home/home_utente/initrd-tree.backup
  • l'immagine initrd
cp /boot/initrd.gz /home/home_utente/initrd.gz.backup

[modifica] Introduzione

Installando o configurando Linux, ci si sarà prima o poi *scontrati* con la necessità di configurare ed installare un initrd image. Il termine *scontro* non è scelto casualmente: pur essendo l'initrd una delle funzionalità del kernel di linux più importanti per il suo funzionamento e per la configurazione del sistema, si tratta di una delle funzionalità più fraintese e peggio conosciute.

Lo scopo fondamentale dell'initrd è mettere a disposizione del kernel linux una serie di file indispensabili al corretto caricamento ed inizializzazione del sistema, come componenti userspace per i driver che usano *connector* (una funzionalità del kernel 2.6 di linux) o moduli altrimenti inacessibili in fase di boot, o più semplicemente di compiere operazioni d'inizializzazione che esulano dal kernel stesso ma dalle quali ne dipende il corretto avvio.

Esempi classici sono quelli in cui il filesystem root è su un filesystem il cui supporto non è compilato staticamente nel kernel, si trovi su un supporto RAID od LVM o su un volume criptato (od una combinazione di questi elementi). Altri esempi possono essere quelli in cui determinati driver necessitano di caricare il firmware da file esterni al kernel stesso oppure in cui il root filesystem non si trova su un disco locale ma remoto, come uno share NFS (per le macchine senza disco).

Lo scopo di questa guida è guidare l'utente attraverso i vari passaggi necessari ad ottenere una corretta conoscenza del funzionamento dell'initrd e del suo utilizzo, tramite gli strumenti forniti dalla distribuzione Slackware GNU/Linux.

[modifica] Nozioni di Base

L'initrd è un filesystem temporaneo caricato dal kernel di linux dopo la fase di boot immediatamente prima il montaggio della partizione di root e l'esecuzione di init (il processo padre di tutti gli altri, responsabile fra le altre cose dell'avvio vero e proprio del sistema).

A questo scopo, nei kernel della serie 2.4 veniva usato il supporto ai ramdisk del kernel linux. In fase d'avvio veniva caricata un archivio cpio compresso con gzip, caricato nel ramdisk e quindi montato con loop. L'aspetto positivo di questo metodo era che funzionava. Gli aspetti negativi erano di natura sistemistica (la necessità di eseguire operazioni privilegiate di root per il montaggio e la manipolazione dell'initrd), lo spreco di risorse da parte del ramdisk (la cui dimensione non è modificabile dinamicamente e quindi in genere sovradimensionata rispetto al reale utilizzo), la notevole quantità di codice e funzionalità richieste nel kernel: la possibilità di decomprimere file gzip, di leggere archivi cpio, di montare filesystem in loop, e via discorrendo.

Nel tempo, questo meccanismo è stato migliorato con l'introduzione del filesystem tmpfs (o shmfs), il quale permetteva una gestione più flessibile e dinamica rispetto al normale ramdisk. Questo metodo a sua volta si è evoluto con l'introduzione del filesystem ramfs, ancora più leggero e flessibile in quanto basato su componenti standard del kernel linux (nella fattispecie la gestione della cache in ram), richiedendo quindi in aggiunta al normale codice del kernel solo la capacità di decomprimere archivi gzip. Questo metodo è diventato uno standard per la gestione dell'initrd nella serie 2.6 del kernel, al punto da dare il proprio nome alla *nuova* initrd, ora chiamata initramfs.

Slackware 12, come ogni distribuzione moderna, usa questa versione leggera e potente, per quanto continui a chiamarle *initrd images" e non initramfs come altre distribuzioni (gentoo ad esempio). Per quanto impreciso questi due termini sono utilizzabili interscambiabilmente.

Ma come viene caricata l'initrd image e quando?

Il come è abbastanza semplice: il bootloader informa il kernel (tramite un opzione apposita che va settata nella configurazione del bootloader) che esiste un initrd image, come si chiama e dove si trova (vedi oltre). Il kernel a sua volta, se ha compilato il supporto all'initrd con tutto ciò che serve, si preoccupa di caricare l'initrd image al momento opportuno: immediatamente dopo la fase di loading del kernel stesso, durante il bootprocess.

Volendo schematizzare (molto) un normale bootprocess, avremo:

1) caricamento del bootloader dall'MBR. Il bootloader può visualizzare o meno un menù, permettere d'impostare opzioni, etc.
2) caricamento del kernel da parte del bootloader. Quest'ultimo passa al kernel una serie di parametri che gli danno 
   informazioni sull'ambiente in cui si dovrà eseguire, fra cui l'identificativo della partizione di root, contenente
   i file veri e propri del sistema.
3) caricamento di init dal filesystem root da parte del kernel, con conseguente inizializzazione del sistema

In presenza di un initrd, fra la fase 2) e la fase 3) vengono inseriti dei passaggi successivi, per cui:

1) caricamento del bootloader dall'MBR
2) caricamento del kernel da parte del bootloader
3.1) caricamento da parte del kernel dell'immagine initrd, un filesystem virtuale contenente una replica 
     ridotta del filesystem reale
3.2) esecuzione di uno pseudo-init presente all'interno dell'initrd
3.3) montaggio del reale root filesystem
4) caricamento di init dal filesystem root da parte dello pseudo-init dell'initrd, con conseguente inizializzazione del sistema

A questo punto, dovrebbe essere chiaro lo scopo dell'avere un initrd image e la sua collocazione nel sistema GNU/Linux. Come fare quindi per creare e gestire un initrd image? Innanzitutto, due paroline sul kernel.

[modifica] Configurazione del Kernel

Slackware 12 viene fornita di default con un kernel 2.6 con supporto initrd, con tutti i tool necessari al suo utilizzo, quindi non è richiesta l'installazione di software aggiuntivi o la ricompilazione del kernel allo scopo di attivare supporti particolari. Nel caso non si stia usando il kernel standard, è necessario verificare che le dovute opzioni siano attivate ed eventualmente ricompilare il kernel. In caso contrario, è possibile evitare questa parte.

Le opzioni richieste si trvano sotto:

General Setup

[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
()    Initramfs source file(s)     

Non sono necessarie altre opzioni particolari.

[modifica] mkinitrd

Come detto precedentemente, un initrd image altro non è che un archivio compresso contenente una replica minimale del filesystem reale. Detto in parole povere, si tratta di creare in una directory una copia del filesystem linux con solo ciò che necessità allo scopo dell'initrd e di comprimerlo con cpio+gzip. Su Slackware linux questa directory è genericamente collocata in /boot/initrd-tree e l'immagine risultante è solitamente /boot/initrd.gz

Come è lecito aspettarsi, nel tempo tutte le distribuzioni hanno iniziato a fornire uno o più tool di gestione dell'immagine initrd. Slackware GNU/Linux non fa certo eccezione ed il suo tool è chiamato "mkinitrd". Con mkinitrd è possibile creare ex-novo initrd-tree con al suo interno tutto ciò che necessita alla creazione di un initrd image, modificarne il contenuto e comprimerle in modo da ottenere le immagini, tutto con pochi parametri di command line.

Analizziamone il funzionamento:

[modifica] Creazione di un nuovo initrd-tree

Il parametro di mkinitrd per la creazione di un nuovo tree è -c. Digitando:

mkinitrd -c

dentro la directory /boot verrà creata la directory initrd-tree, eliminando quella vecchia con tutti il suo contenuto nel caso sia presente. Allo stesso tempo verrà creata immediatamente una nuova immagine compressa dell'initrd, in /boot/initrd.gz. Genericamente, è meglio specificare in fase di creazione almeno la collocazione ed il tipo di filesystem della partizione di root. A tal scopo è possibile utilizzare i seguenti parametri:

  • -r : permette d'indicare il device rappresentante la partizione di root
  • -f : permette di specificare il tipo di filesystem utilizzato dalla partizione di root

Pertanto, ipotizzando che la nostra partizione di boot sia /dev/hda2 con filesystem ext3, scriveremo:

mkinitrd -c -r /dev/hda2 -f ext3

E' bene ricordarsi che il flag -c causa l'eliminazione del precedente initrd-tree. Se si desidera semplicemente variare opzioni di un initrd-tree esistente è quindi sufficiente ometterlo.

Imputando il comando privo di qualsiasi opzione, si aggiornerà l'immagine esistente lasciando invariato il contenuto del tree.

[modifica] Attivazione dei supporti speciali

Come anticipato nell'introduzione, l'initrd-tree viene genericamente usato per l'inizializzazione di partizoni di root criptate o che fanno uso di LVM. A questo scopo, mkinitrd mette a disposizione due comodi switch:

  • -L : attiva il supporto ad LVM
  • -C : attiva il supporto a cryptsetup (quest'opzione richiede che sia specificato anche -r, vedi sopra)

Pertanto, supponendo di voler aggiungere all'initrd creata sopra il supporto ad LVM, sarà sufficiente digitare:

mkinitrd -L

Ovviamente è possibile specificare questi switch insieme agli altri, non è necessario richiamare due o più volte mkinitrd se si sa fin dal principio quali opzioni vorremo usare.

Purtroppo non esistono switch che permettono di attivare il supporto a RAID, ma si vocifera che saranno disponibili dalla prossima versione di mkinitrd. Nel mentre, è possibile aggiungere il supporto manualmente (vedi oltre).

[modifica] Caricamento di moduli aggiuntivi

Come detto precedentemente, una delle potenzialità dell'initrd è mettere a disposizione del kernel linux file altrimenti non disponibili durante la fase di boot. Supponiamo ad esempio che il supporto al filesystem della partizione di root non sia compilato staticamente nel kernel: ne consegue naturalmente che il kernel dovrebbe caricare il file del modulo per poter accedere al filesystem, ma essendo questo file scritto all'interno di un filesystem di cui non ha il supporto nativo, ne consegue un discreto paradosso.

Parlando di Slackware GNU/Linux, questo è il caso ad esempio di reiserfs, compilato nel kernel di default come modulo. Con l'initrd è possibile aggirare quest'ostacolo inserendo il modulo del kernel nell'immagine initrd. In questo modo il kernel può caricarlo prima di tentare di accedere al root filesystem. I parametri utilizzati a questo scopo sono 2:

  • -k : permette di specificare la versione del kernel da cui attingere i moduli
  • -m : permette di specificare la lista di moduli, separati da virgola, da includere nell'initrd

Quindi, volendo includere il modulo reiserfs.ko per il kernel 2.6.21.5 nell'initrd-tree attuale, scriveremo:

mkinitrd -k 2.6.21.5 -m reiserfs

E' bene ricordarsi che ogni volta che si vuole includere un modulo nuovo, bisogna specificare tutta la lista dei moduli precedenti, in quanto viene sovrascritta. Per essere sicuri di scrivere correttamente la versione del kernel, è sufficiente controllare il contenuto della directory /lib/modules

[modifica] Localizzazione dell'initrd

Su linux è pratica comune lavorare con più kernel contemporaneamente. Se questo è il nostro caso, potrebbe essere necessario creare più immagini initrd, in modo da caricare i moduli giusti per la versione desiderata del kernel. Fortunatamente mkinitrd ci permette di lavorare con più initrd contemporaneamente senza obbligarci a particolari salti mortali, tramite i seguenti parametri:

  • -s : permette di specificare un percorso alternativo per l'initrd-tree
  • -o : permette di specificare un nome differente per l'initrd image

Quindi, ad esempio, supponendo di voler creare un nuovo initrd-tree specifico per il kernel 2.6.21.5-smp (il kernel di default di Slackware 12), con supporto LVM, filesystem root reiserfs su /dev/hda2 e caricare il modulo per reiser, scriveremo:

mkinitrd -s /boot/initrd-tree-2.6.21.5-smp -o /boot/initrd.gz-2.6.21-smp -c -r /dev/hda2 -f reiserfs -L -k 2.6.21.5 -m reiserfs

et-voilà! il gioco è fatto. E' bene ricordarsi che se si lavora con tree differenti del kernel usando queste due opzioni, bisognerà specificarle entrambe ogni volta che si usa il comando mkinitrd per modificare o aggiornare il tree o l'immagine relativa.

A questo punto rimane solo la necessità di assicurarsi che il bootloader sia a conoscenza dell'esistenza di un initrd.

[modifica] Configurazione di Lilo

Perchè un immagine initrd sia caricata dal kernel, come detto precedentemente è indispensabile che il bootloader gli comunichi che esiste. Su Slackware 12 il bootloader di default è lilo, pertanto è necessario modificare la configurazione di lilo per far si che l'initrd venga caricata e funzioni.

Il file in questione è /etc/lilo.conf. E' sufficiente, in ogni voce che lo richiede, inserire la direttiva "initrd=..", specificando il giusto nome dell'initrd. Ad esempio, supponendo di continuare l'esempio precedente in cui abbiamo creato l'immagine /boot/initrd.gz-2.6.21-smp, sarà sufficiente modificare il file lilo.conf in questo modod:

# Linux bootable partition config begins
image = /boot/vmlinuz-generic-2.6.21.5-smp
        initrd = /boot/initrd.gz-2.6.21.5-smp
        root = /dev/hda2
        label = Linux26215
        read-only
# Linux bootable partition config ends

quindi digitare l'immancabile "lilo" privo di parametri per aggiornare l'MBR.

[modifica] Personalizzazione manuale dell'initrd per l'aggiunta del supporto a RAID

Il kernel Linux, fra le sue altre meraviglie, mette a disposizione un supporto RAID software completo. Nel caso in cui si voglia utilizzare la partizione di root con una configurazione raid, è necessario utilizzare un initrd, in quanto come accade per LVM l'inizializzazione del dispositivo dev'essere effettuata prima che il kernel acceda alla partizione stessa.

Purtroppo, come accennato il tool mkinitrd nella versione di Slackware 12 non include un supporto automatico alla configurazione di RAID. E' però possibile aggirare l'ostacolo eseguendo l'operazione manualmente con pochi semplici passaggi.

NB: La configurazione di RAID esula dallo scopo di questo articolo, 
    si presume che sia presente un array RAID configurato e funzionante.

Innanzitutto, è necessario creare un initrd-tree come specificato precedentemente, passando tutte le dovute opzioni. Ad esempio, supponendo che la partizione di root abbia filesystem ext3 e si trovi sulla periferica raid /dev/md0

mkinitrd -c -r /dev/md0 -f ext3

A questo punto, è necessario entrare all'interno dell'initrd-tree e compiere alcune operazioni manualmente.

cd /boot/initrd-tree

Come si potrà notare, eseguendo un semplice ls, la struttura è molto simile a quella del filesystem reale:

root@nuitari-inspiron:/boot/initrd-tree# ls -la
total 19
drwxr-xr-x 11 root root 1024 2008-03-22 15:49 .
drwxr-xr-x  4 root root 1024 2008-03-22 15:50 ..
drwxr-xr-x  2 root root 1024 2007-06-03 03:23 bin
drwxr-xr-x  7 root root 1024 2008-03-14 16:03 dev
drwxr-xr-x  3 root root 1024 2008-03-14 16:02 etc
-rwxr-xr-x  1 root root 4014 2008-03-14 15:28 init
-rw-r--r--  1 root root   10 2008-03-14 15:18 initrd-name
drwxr-xr-x  4 root root 1024 2008-03-14 16:03 lib
-rw-r--r--  1 root root  152 2008-03-14 15:28 load_kernel_modules
-rw-r--r--  1 root root    0 2007-06-27 22:56 luksdev
drwxr-xr-x  2 root root 1024 2004-03-01 00:20 mnt
drwxr-xr-x  2 root root 1024 2004-03-01 00:21 proc
drwxr-xr-x  2 root root 1024 2008-03-14 16:03 root
-rw-r--r--  1 root root    9 2008-03-14 15:18 rootdev
-rw-r--r--  1 root root    5 2008-03-14 15:18 rootfs
drwxr-xr-x  2 root root 1024 2007-06-03 03:22 sys

Innanzitutto, è necessario creare i device all'interno della directory dev, copiandoli dalla /dev del filesystem root:

cp -a /dev/md* dev/

Dopo aver fatto questo, è necessario copiare l'utility mdadm all'interno della directory sbin, la quale innanzitutto va creata:

mkdir sbin
cp -p /sbin/mdadm sbin/

A questo punto, è necessario copiare il proprio file mdadm.conf nella directory etc. Spesso il file mdadm.conf non è configurato correttamente, in quanto i normali script d'avvio di Slackware sono capaci di auto-rilevare la configurazione dell'array raid. Se questo è il nostro caso, è possibile creare direttamente il file mdadm.conf con la seguente sintassi:

mdadm --examine --scan > etc/mdadm.conf

Se non è questo il caso, semplicemente copiamolo dalla directory /etc

cp /etc/mdadm.conf etc/

L'ultima cosa che rimane da fare è modificare lo script "init" (il corrispettivo del normale init all'interno dell'initrd, come accennato precedentemente) in modo che venga eseguito mdadm al momento giusto. Scriviamo le righe necessarie fra il caricamento dei moduli e l'inizializzazione dei volumi LVM:

[...]
    unset module
  fi
fi

# rebuild RAID ARRAY
/sbin/mdadm --assemble /dev/md0

# Initialize LVM:
if [ -x /sbin/vgscan ]; then
  /sbin/vgscan --mknodes --ignorelockingfailure
[...]

Fatto ciò, dobbiamo semplicemente aggiornare l'immagine eseguendo mkinitrd privo di parametri, quindi aggiornare lilo. Ovviamente, se abbiamo localizzato l'immagine initrd, non dovremo usare mkinitrd completamente privo di parametri ma quantomeno specificare la coppia -s e -o, come ampiamente chiarito in precedenza.

[modifica] Conclusioni

Abbiamo analizzato lo scopo, il funzionamento e la creazione di un initrd. Le possibilità offerte da questa potente funzionalità del kernel Linux sono molte e dopo la lettura di questo articolo si dovrebbe aver acquisito le conoscenze e la padronanza degli strumenti necessari per un utilizzo consapevole ed indipendente.

[modifica] FAQ

[modifica] Ringraziamenti

Autore: Samuele "Nuitari" Diella - samuele.diella@gmail.com

[modifica] Articoli Correlati

Slackware LVM2 HOWTO

[modifica] Links Esterni

Strumenti personali
Namespace

Varianti