2.3 Avvio del sistema
Una volta che il boot loader è stato avviato, questo carica il
kernel,
lo decomprime (negli elaboratori X386 questa operazione avviene in protected
mode),
e lo avvia passandogli eventuali parametri. Il kernel si preoccupa di compiere le operazioni
necessarie all’avvio dell’intero sistema operativo, ovvero dei processi fondamentali per il suo
utilizzo.
L’unico processo che viene avviato dal kernel è init tramite l’esecuzione del
file /sbin/init (man page init(8)), il quale poi si preoccupa di avviare gli
altri.
____________________________________________________________________
Comando: init
Path: /sbin/init
SINTASSI
# init [option] [runlevel]
DESCRIZIONE
-
option indica la modalità di funzionamento di init. Può assumere i seguenti valori
-
-a | auto
indica che il kernel è stato caricato con la riga di comando di default.
Questo fa impostare ad init la variabile di ambiente AUTOBOOT con
il valore “yes”;
-
-b | emergency
lancia direttamente una shell in modalità monoutente senza eseguire
nessuno script di startup;
-
-s | S | single
modalità di avvio monoutente (single-user). In tale modalità, prima
di avviare la shell, viene elaborato il file /etc/inittab e quindi
eseguiti gli script rc;
-
-z xxx ignora l’argomento xxx. Aumenta la riga di comando di init
(occupando più stack) in modo che il comando ps possa visualizzare
il runlevel corrente;
-
runlevel indica la modalità di funzionamento del sistema. Può assumere uno dei seguenti
valori
-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
imposta il sistema con il runlevel relativo;
-
S | s imposta il sistema in una particolare modalità single-user, ovvero
init avvia il sistema senza l’ausilio del file /etc/inittab,
presentando automaticamente una shell con i privilegi del superuser
sulla console di sistema (/dev/console);
____________________________________________________________________
Il processo init imposta le seguenti variabili di ambiente per i processi figli (tutti i
processi da esso lanciati)
-
PATH /usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin è l’elenco delle directory
nel quale vengono ricercati i file eseguibili specificati sulla riga di comando;
- INIT_VERSION
indica la versione di init;
- RUNLEVEL
indica il runlevel corrente;
- PREVLEVEL
indica il runlevel precedente;
- CONSOLE
indica il dispositivo associato alla conosle di sistema. Tale valore viene impostato
dal kernel. Nel caso in cui ciò non avvenga, viene impostato a /dev/console;
La sequenza di avvio dei processi iniziali utilizza un meccanismo derivato da Unix System
V ,
secondo il quale init legge il contenuto del file /etc/inittab (man page inittab(5)) che
contiene le direttive per l’avvio degli altri processi necessari al funzionamento del sistema.
Tale file, come la quasi totalità dei file di configurazione dei sistemi Unix-like, è in formato
testo (ASCII).
La sintassi delle righe contenute nel file /etc/inittab è la seguente:
id:runlevel:action:file
dove
-
id è un’etichetta che identifica univocamente la riga all’interno del file. Può essere
lunga al massimo 2 caratteri;
-
runlevel
è l’elenco dei runlevel
in corrispondenza dei quali deve essere presa in considerazione la riga;
-
action è una direttiva che indica a init l’azione da intraprendere. Le possibili direttive
sono:
-
respawn
Il file viene lanciato ed ogni volta che il processo da esso generato termina,
viene rilanciato automaticamente;
-
wait Il file viene lanciato e init attende che il processo da questo avviato
sia terminato prima di procedere nell’elaborazione delle altre righe di
/etc/inittab;
-
once Il file viene lanciato una sola volta;
-
boot Il file viene lanciato ignorando il runlevel corrente;
-
bootwait
Il file viene lanciato ignorando il runlevel corrente e init attende
la terminazione del processo avviato da file prima di procedere
nell’elaborazione delle altre righe di /etc/inittab;
-
off Non esegue alcuna operazione;
-
ondemand
La riga viene presa in considerazione quando lo specifico ondemand
runlevel è richiesto, senza però cambiare il runlevel corrente. Gli
ondemand runlevel possibili sono a, b e c;
-
initdefault
Imposta il runlevel corrente del sistema all’avvio al valore di runlevel. Il
campo runlevel deve contenere un solo valore che identifica il runlevel da
impostare. Il file viene ignorato. Se nessuna riga specifica questa direttiva,
init richiede all’utente di inserire il valore del runlevel con cui avviare
il sistema;
-
sysinit
Il file viene lanciato ignorando il runlevel corrente. Tale riga viene presa
in considerazione prima di quelle contenenti boot, bootwait e di quelle
relative a runlevel specifici;
-
powerwait
Il file viene lanciato quando l’alimentazione viene a mancare. Il sistema
è in grado di rilevare questo stato quando un UPS è opportunamente
connesso a quest’ultimo. init attende la terminazione del processo
lanciato da file prima di procedere;
-
powerfail
È analogo a powerwait tranne per il fatto che init non attende la
terminazione del processo lanciato da file;
-
powerokwait
Il file viene lanciato quando l’alimentazione è stata ripristinata. Il sistema
è in grado di rilevare questo stato quando un UPS è opportunamente
connesso a quest’ultimo. init attende la terminazione del processo
lanciato da file prima di procedere;
-
powerfailnow
Il file viene lanciato quando la batteria dell’UPS è quasi scarica e
l’alimentazione generale non c’è. Il sistema è in grado di rilevare questo
stato quando un UPS è opportunamente connesso a quest’ultimo;
-
ctrlaltdel
Il file viene lanciato quando init riceve il segnale SIGINT.
Questo vuol dire che è stata premuta la combinazione di tasti
(o
dipende dal tipo di tastiera);
-
kbrequest
Il file viene lanciato quando init riceve un segnale dal gestore (handler)
della tastiera. Per far funzionare questa direttiva è opportuno segnalare
al gestore della tastiera di notificare la pressione di una determinata
combinazione di tasti a init;
-
file è il file (ovvero il suo path assoluto) da eseguire, nel caso in cui la direttiva lo
richieda.
Al suo avvio, init cerca nel file /etc/inittab una riga contenente la stringa initdefault,
che imposta il runlevel di avvio del sistema. Se tale indicazione non viene trovata
(o addirittura il file /etc/inittab non esiste), init ne richiede l’inserimento da
tasiera.
Dopo che init ha lanciato tutti i processi indicati in /etc/inittab, attende che si
verifichi una delle seguenti condizioni:
-
• uno dei processi lanciati da init termina;
-
• init riceve un segnale di mancata alimentazione SIGPWR;
-
• init riceve la richiesta di cambiamento di runlevel (da telinit);
Quando si verifica una delle condizioni sopra elencate init riesamina il file /etc/inittab. Si
può anche forzare init a riesaminare il file /etc/inittab con il comando
# telinit q
Se il sistema non è in single-user mode e init riceve il segnale SIGPWR, quest’ultimo tenta
di leggere il contenuto del file /etc/powerstatus che riporta i dettagli relativi al segnale in
questione
-
F (Fail) l’alimentazione è mancata e l’UPS sta erogando energia. In tal caso init
esegue le direttive powerwait e powerfail presenti nel file /etc/inittab;
-
O (Ok) l’alimentazione è stata ripristinata. In tal caso init esegue la direttiva
powerokwait presente nel file /etc/inittab;
-
L (Low) l’alimentazione è mancata e l’UPS sta esaurendo la sua energia. In tal
caso init esegue la direttiva powerfailnow presente nel file /etc/inittab;
Nel caso in cui il file /etc/powerstatus non esista o contenga qualcosa di diverso
dalle lettere sopra riportate, init esegue le operazioni relative al caso in cui il file
/etc/powerstatus esista e contenga la lettera F.
La gestione del segnale SIGPWR è comunque obsoleta ed è consigliabile interagire con init
per mezzo del dispositivo /dev/initctl.
Quando init riceve la richiesta di cambiamento di runlevel, invia il segnale SIGTERM a
tutti i processi (che appartengono allo stesso process group che init aveva creato inizialmente
- gli altri processi devono essere terminati manualmente) che non sono definiti nel nuovo
runlevel. Quindi attende 5 secondi prima di inviare ad essi il segnale SIGKILL che ne forza la
terminazione immediata.
Il segnale SIGTERM richiede ad un processo quella che viene definita graceful
termination, cioè la sua terminazione “dolce”. Questo significa che il processo stesso deve
gestire la propria terminazione quando riceve tale segnale, poiché soltanto esso sa se deve
compiere delle operazioni in corso, prima di terminare effettivamente (es. chiudere i file
aperti, ...). Il segnale SIGKILL invece indica al kernel stesso di terminare un processo
all’istante (immediate termination). Questo segnale è da considerarsi l’ultima spiaggia per
la terminazione di un processo poiché non ha nessun controllo sulle operazioni ancora non
concluse da parte del processo che deve essere terminato (si può rischiare di perdere dei
dati).
Quando un processo lanciato da init termina, init memorizza l’evento nel
system status file (/var/run/utmp e /var/log/wtmp).
|
Un esempio del contenuto del file /etc/inittab è riportato di seguito.
#
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
#
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
# Modified for RHS Linux by Marc Ewing and Donnie Barnes
#
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault:
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
# Things to run in every runlevel.
ud::once:/sbin/update
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, assume we have a few minutes
# of power left. Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
# xdm is now a separate service
x:5:respawn:/etc/X11/prefdm -nodaemon
Quando init deve lanciare in esecuzione un file filename, tenta di eseguirlo per
mezzo del file /etc/initscript (man page initscript(5)), passandogli anche
le indicazioni relative alla riga di /etc/inittab che in quel momento init sta
considerando. Il file /etc/initscript potrebbe essere uno script che serve per definire delle
variabili di ambiente e altre impostazioni che riguardano l’interpretazione degli script
della procedura di inizializzazione del sistema. Nel caso in cui /etc/initscript
non esista (situazione standard), i file sono lanciati in esecuzione direttamente da
init.
In genere, il primo file lanciato in esecuzione da init è /etc/rc.d/rc.sysinit (v. riga
che si riferisce alla direttiva sysinit nel file /etc/inittab) che si occupa di eseguire le
seguenti operazioni:
-
• montare il filesystem /proc;
-
• impostare l’ora dell’orologio del sistema (clock) a quella dell’orologio del BIOS;
-
• impostare il layout della tastiera (keymap) ed i caratteri del sistema (font);
-
• attivare il funzionamento dell’interfaccia di rete;
-
• inizializzare il controller USB (Universal Serial Bus);
-
• eseguire un controllo di integrità sul filesystem nel caso si accorga che il precedente
spegnimento del sistema sia avvenuto in modo non corretto.
-
• inizializzare la gestione dei quota relativi alla partizione montata come root directory;
-
• inizializzare i dispositivi ISA PNP (Plug’N’Play);
-
• ri-montare la partizione relativa alla root directory (/) in lettura/scrittura;
-
• inizializzare il LVM (Logical Volume Management);
-
• attivare lo swap;
-
• avviare i dispositivi RAID;
-
• inizializzare il LVM per i dispositivi RAID;
-
• montare le altre partizioni;
-
• riconfigurare la macchina se non è configurata;
-
• inizializzare le porte seriali;
-
• caricare il modulo per la gestione dei nastri SCSI (se rilevati);
-
• inizializzare il controller Firewire (se rilevato);
-
• attivare le ottimizzazioni per l’accesso ai dischi.
Quindi vengono avviati i servizi (daemon) necessari per l’utilizzo del sistema e vengono
aperti i terminali per far accedere gli utenti al sistema, generalmente per mezzo di un apposito
script come /etc/rc.d/rc (v. sez. 2.7).
Alla fine dell’elaborazione di /etc/inittab, init lancia in esecuzione il file /etc/
rc.d/rc.local (se esiste) che può essere quindi creato o modificato dall’amministratore del
sistema per personalizzare la procedura di avvio.