Abbiamo presentato nelle pagine precedenti il fondamentale init, senza però soffermarci troppo sulle spiegazioni; in questa pagina cercheremo di fare più luce su questo importantissimo 'personaggio'.
Prima di parlarne, comunque, dobbiamo introdurre il discorso dei runlevel: un runlevel, tecnicamente parlando, è una configurazione software del sistema che permette l'esistenza solo di un gruppo selezionato di processi. Più semplicemente, un runlevel è uno stato del sistema in cui possono venire compiute solo determinate operazioni. I runlevel sono sette, enumerati da 0 a 6, sebbene esistano anche il 7, l'8 ed il 9 che però i normali Unix (e Linux con loro) non utilizzano. Lo 0, l'1 ed il 6 sono riservati e corrispondono rispettivamente a: arresto del sistema (0), single-user mode (1) e reboot (6). Gli altri, invece, corrispondono alla modalità multi-user, ossia il normale stato operativo del sistema.
Detto questo, che comunque capirete meglio in seguito, torniamo ad init. Init è detto il padre dei processi, quello cioè che "dà vita" a tutti gli altri processi avviati, in automatico o per esplicita richiesta di un utente, dalla macchina. Come processo principale, init ha PID uguale ad uno; il PID (Process ID) è un numero, assegnato automaticamente secondo sequenza dal sistema, che identifica univocamente un processo, sia esso automatico (cioè avviato in automatico dal sistema operativo) oppure lanciato da un utente. Come possiamo dimostrare che init ha PID uguale ad uno? Utilizzando il comando "ps", che visualizza i processi attivi, con l'opzione "x", che riporta i processi avviati senza terminale di controllo: nel risultato potreste leggere (anzi, leggerete!) qualcosa del genere:
PID TTY STAT TIME COMMAND
1 ? S 0:05 init [2]
Le colonne che ci interessano sono PID, TTY (terminale su cui è in esecuzione il programma), STAT (lo stato del programma stesso; S è sinonimo di sleeping) e COMMAND, che ovviamente mostra il nome del programma.
Visto cos'è init, veniamo a come in pratica questo venga invocato. Esso viene chiamato in causa all'avvio dopo il boot del kernel e, come prima cosa, legge il file /etc/inittab per trovare il runlevel di default al quale portare il sistema: nel caso della mia distribuzione è il 2, sebbene anche se fosse stato 3, 4 o 5 non ci sarebbe stata differenza! (se non erro, RedHat e sue derivate utilizzano il 3 come runlevel di default)
Ma cos'è il runlevel 2 e cosa lo differenza dagli altri? La definizione di runlevel è già stata data in precedenza, quello che si vuole mettere qui in evidenza è cosa comporta nel sistema il raggiungimento di tale runlevel. A questo scopo, dobbiamo rivolgerci ancora al file /etc/inittab, nel quale sono presenti le righe:
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
Vediamo innanzitutto la sintassi di queste righe, riportabile al modello:
id:runlevel:azione:processo
Quindi, al runlevel che ci interessa esaminare, il secondo, viene invocata l'azione "wait", che indica ad init di avviare il processo ed attenderne la terminazione; il processo che viene avviato è /etc/init.d/rc con un "2" come argomento. Cos'è questo programma "rc" che viene richiamato? Esso non è altro che uno script di shell, che, dopo opportuni controlli ed accorgimenti, si porta nella directory /etc/rcX.d e ne esegue gli script contenuti. Alla "X" che abbiamo utilizzato va comuque sostituito l'argomento passato come opzione al comando rc: quindi, nel caso del runlevel 2, rc si porterà nella directory /etc/rc2.d.
Detto questo, esaminiamo il contenuto della directory /etc/rc2.d e, in generale, di tutte le altre /etc/rcX.d. Vediamo intanto cosa contengono, utilizzando il probabilmente noto comando "dir" (ma dimenticatelo in fretta visto che poi utilizzeremo solo il comando "ls"!):
dir /etc/rc2.d
il cui output è:
S10sysklogd S20anacron S20gpm S20makedev S50proftpd
S99rmnologin S12kerneld S20apmd S20inetd S20postgresql
S89cron S14ppp S20exim S20logoutd S20xfs
S91apache
Come vedete, ogni file ha il nome composto da tre parti: una S o una K (in questo caso solo una S!) che indicano se il processo deve essere avviato (S = start) o interrotto (K = kill), un numero, che indica la priorità con cui questi devono essere avviati ed il nome del processo. Vediamo un esempio: l'avvio di gpm (il demone che gestisce il mouse) è precedente all'avvio si apache, visto che gpm ha un id numerico 20 contro il 91 di apache. L'id numerico qui riportato non ha comunque nulla a che fare con il PID che il programma si vedrà assegnato dal sistema: il numero che qui precede il nome del programma è utilizzato per definire al priorità con la quale vengono avviati i processi!
Quindi, una volta che init verrà avviato, lancerà il programma "rc" che si incaricherà di avviare i servizi citati in /etc/rc2.d
Apriamo prima di chiudere due parentesi: ricordate che precedentemente abbiamo detto che i runlevel 2, 3, 4 e 5 sono equivalenti? Alla luce di quanto detto, adesso possiamo dimostrarlo. A parte forzare un cambiamento di runlevel (attuabile con il comando telinit seguito dal numero di runlevel) e notare che ... non succede niente, vediamolo più tecnicamente. Utilizzeremo il programma "diff" che visualizza in output le differenza fra due file o due directory: lanciando in sequenza
diff /etc/rc2.d /etc/rc3.d
diff /etc/rc2.d /etc/rc4.d
diff /etc/rc2.d /etc/rc5.d
il comando non darà alcun output. Se invece lanciamo:
diff /etc/rc2.d /etc/rc1.d
verranno stampate a video le differenze fra le directory (lasciamo a voi la prova!)
La seconda parentesi da aprire è dedicata a occhi più "tecnici": forse qualcuno avrà notato che i file presenti in, ad esempio, /etc/rc2.d, non sono veri e proprio file, bensì dei link che puntano a degli script che portano il nome del link senza la S o la K ed il numero presenti in /etc/init.s; ad esempio, /etc/rc2.d/S91apache punta a /etc/init.d/apache. Tutti gli script linkati in /etc/rcX.d sono presenti in /etc/init.d, così che possano essere utilizzati come e quando serve all'entrata di ogni runlevel!
Comunque, per chiudere, vogliamo tranquillizzarvi: abbiamo descritto init e runlevel abbastanza approfonditamente più che altro per rendere chiari i meccanismi di avvio del sistema; tutti i link e gli script necessari saranno installati automaticamente all'installazione del sistema o di un nuovo programma che avrà bisogno di essere lanciato all'avvio, a meno che vogliate scrivere un vostro programma che debba essere automaticamente avviato al boot e interrotto allo shutdown del sistema!