Sistema 5 init
ti racconterà solo una piccola parte della storia.
C'è una sorta di miopia che affligge il mondo Linux. La gente pensa di usare una cosa chiamata "Sistema 5 init
", e questo è sia ciò che è tradizionale che il miglior punto di partenza. Nessuno dei due è infatti il caso.
Tanto per cominciare, la tradizione non è ciò che queste persone dicono che sia. Sistema 5 init
e Sistema 5 rc
risale a AT&T UNIX System 5, che era quasi tanto lontano dopo il primo UNIX quanto lo siamo ora (diciamo) dopo la prima versione di Linux-Mandrake.
UNIX della prima edizione aveva solo init
. Non aveva rc
. Il linguaggio assembly della prima edizione init
(il cui codice è stato ripristinato e reso disponibile da Warren Toomey et al.) generato e rigenerato direttamente 12 getty
process, ha montato 3 filesystem cablati da una tabella incorporata ed ha eseguito direttamente un programma dalla home directory di un utente chiamato mel
. Il getty
table era anche direttamente nell'immagine del programma.
Fu un altro decennio dopo UNIX System 5 che arrivò il cosiddetto sistema di init Linux "tradizionale". Nel 1992, Miquel van Smoorenburg ha (ri)scritto un init
per Linux +rc
e i relativi strumenti associati, che ora le persone chiamano "System 5 init
", anche se in realtà non è il software di UNIX System 5 (e non è solo init
).
Sistema 5 init
/rc
non è il miglior punto di partenza, e anche se si aggiunge la conoscenza di systemd che non copre la metà di ciò che c'è da sapere. C'è stato molto lavoro nell'area della progettazione del sistema init (per Linux e BSD) che è avvenuto solo negli ultimi due decenni. Tutti i tipi di decisioni ingegneristiche sono state discusse, prese, progettate, implementate e messe in pratica. Anche gli Unices commerciali hanno fatto molto.
Sistemi esistenti da cui studiare e imparare
Ecco un elenco incompleto di alcuni dei principali sistemi init diversi da quei due, e uno o due dei loro (diversi) punti salienti:
- Il finit di Joachim Nilsson ha seguito la strada dell'utilizzo di un file di configurazione più leggibile dall'uomo.
- Il minit di Felix von Leitner ha optato per un sistema di configurazione del filesystem-è-il-database, piccoli footprint di memoria e dipendenze start/stop tra le cose che
init
inizia. - Il runit di Gerrit Pape è andato per quello che ho precedentemente descritto come i soli script di generazione di quattro shell approccio.
- InitNG mirava ad avere dipendenze, destinazioni denominate, più file di configurazione e una sintassi di configurazione più flessibile con un intero carico di più impostazioni per i processi figli.
- upstart ha optato per una riprogettazione completa, modellando il sistema non come servizi e interdipendenze, ma come eventi e lavori attivati da essi.
- Il design di nosh include l'eliminazione di tutta la gestione del servizio (incluso anche il
getty
deposizione delle uova e mietitura di zombi) in un gestore di servizi separato e solo gestione di dispositivi/link simbolici/directory "API" specifici del sistema operativo e eventi di sistema. - sinit è un init molto semplice. Esegue
/bin/rc.init
il cui compito è avviare programmi, montare filesystem, ecc. Per questo puoi usare qualcosa come minirc.
Inoltre, circa 10 anni fa, ci fu una discussione tra gli utenti di daemontools e altri sull'uso di svscan
as process #1, che ha portato a progetti come lo studio svscan as process 1 di Paul Jarc, le idee di Gerrit Pape e lo svscan as process 1 di Laurent Bercot.
Il che ci porta a cosa fanno i programmi di processo n. 1.
Cosa fanno i programmi di processo n. 1
Le nozioni su ciò che il processo n. 1 "dovrebbe" fare sono per loro natura soggettive. Un obiettivo significativo il criterio di progettazione è ciò che il processo n. 1 deve almeno fare. Il kernel impone diversi requisiti su di esso. E ci sono sempre alcune cose specifiche del sistema operativo di vario tipo che deve fare. Quando si tratta di quale processo n. 1 ha tradizionalmente fatto, allora non siamo a quel minimo e non lo siamo mai stati davvero.
Ci sono molte cose che vari kernel del sistema operativo e altri programmi richiedono al processo n. 1 a cui semplicemente non si può sfuggire.
La gente ti dirà che fork()
ing le cose e agire come genitore di processi orfani è la funzione principale del processo #1. Ironia della sorte, questo non è vero. La gestione dei processi orfani è (con i recenti kernel Linux, come spiegato su https://unix.stackexchange.com/a/177361/5132) una parte del sistema che si può ampiamente scomporre dal processo n. 1 in altri processi, come un responsabile del servizio dedicato . Tutti questi sono gestori di servizi, che si esauriscono con il processo n. 1:
- l'IBM AIX
srcmstr
programma, il controller delle risorse di sistema runsvdir
di Gerrit Pape da runit- Il
svscan
di Daniel J. Bernstein da daemontools,svscan
di Adam Sampson da freedt,svscan
di Bruce Guenter da daemontools-encore es6-svscan
di Laurent Bercot da s6 - Il
perpd
di Wayne Marshall da perp - la struttura di gestione dei servizi in Solaris 10
- il
service-manager
da nosh
Allo stesso modo, come spiegato su https://superuser.com/a/888936/38062, l'intero /dev/initctl
l'idea non deve essere neanche lontanamente vicina al processo n. 1. Ironia della sorte, è il systemd altamente centralizzato che dimostra che può essere rimosso dal processo n. 1.
Al contrario, le cose obbligatorie per init
, che le persone di solito dimenticano nei loro progetti improvvisati, sono cose come la gestione di SIGINT
, SIGPWR
, SIGWINCH
, e così via inviati dal kernel e che attivano le varie richieste di modifica dello stato del sistema inviate da programmi che "sanno" che determinati segnali al processo n. 1 significano determinate cose. (Ad esempio:come spiegato su https://unix.stackexchange.com/a/196471/5132, i set di strumenti BSD "sanno" che SIGUSR1
ha un significato specifico.)
Ci sono anche attività di inizializzazione e finalizzazione una tantum a cui non si può sfuggire o che soffriranno molto se non vengono eseguite, come il montaggio di filesystem "API" o lo svuotamento della cache del filesystem.
Le basi per gestire i filesystem "API" sono leggermente diverse dal funzionamento di init
rom 1st Edition UNIX:uno ha un elenco di informazioni cablate nel programma e uno semplicemente mount()
Sono tutte le voci nell'elenco. Troverai questo meccanismo in sistemi diversi come BSD (sic!) init
, attraverso il nosh system-manager
, a systemd.
"imposta il sistema per una semplice shell"
Come hai osservato, init=/bin/sh
non ottiene i file system "API" montati, si blocca in modo sgraziato senza svuotamento della cache quando si digita exit
(https://unix.stackexchange.com/a/195978/5132), e in generale lascia al (super)utente il compito di eseguire manualmente le azioni che rendono il sistema minimamente utilizzabile.
Per vedere cosa in realtà non si ha altra scelta che fare nei programmi di processo n. Il minit di Leitner e il system-manager
programma dal pacchetto nosh. I primi due mostrano due tentativi di essere minimalisti, ma gestiscono ancora le cose che è impossibile evitare.
Quest'ultimo è utile, suggerisco, per la sua ampia immissione manuale per system-manager
programma, che specifica esattamente quali filesystem "API" sono montati, quali attività di inizializzazione vengono eseguite e quali segnali vengono gestiti; in un sistema che di progettazione ha il gestore di sistema che genera solo altre tre cose (il gestore del servizio, un logger di accompagnamento e il programma per eseguire i cambiamenti di stato) e fa solo l'inevitabile nel processo n. 1.
System V init su Debian (ci sono altre varianti e variazioni) fa quanto segue:
- Quando si entra in un runlevel, chiama gli script in
/etc/rcX.d/S*
in ordine alfanumerico, doveX
è il runlevel. Questi script dovrebbero impostare il runlevel. La configurazione tipica avvia i daemon ed esegue le attività di configurazione per quel livello di esecuzione. Questa è una cosa che si fa una volta sola quando si accede al runlevel. - Mentre si trova in un livello di esecuzione, avvia i demoni elencati in
/etc/inittab
poiché devono essere attivi durante quel runlevel. Se quei demoni smettono di funzionare, li riavvia. Mentre puoi avere qualsiasi demone che vuoi gestito dainit
, come minimo vuoi qualchegetty
così puoi accedere.getty
esce una volta completato l'accesso, quindiinit
lo riavvia, fornendo un nuovo prompt di accesso.
- Se il demone si riavvia troppe volte in un tempo troppo breve, smette di tentare di riavviarlo per un po'.
- Solo perché qualcosa è stato avviato dagli script di kickoff quando si entra nel livello di esecuzione non fa
init
prova automaticamente a mantenerlo in esecuzione. Devi specificarlo separatamente nel/etc/inittab
.
- Quando si esce da un runlevel, chiama gli script in
/etc/rcX.d/K*
in ordine alfanumerico, doveX
è il runlevel. Un modo per implementare l'arresto o il riavvio è definire un runlevel per quegli eventi e rendere l'ultima attività eseguita comehalt
oreboot
comando. - Chiamerà gli eseguibili in risposta a determinati eventi, come eventi di alimentazione o Ctrl-Alt-Canc.
- E' in ascolto su un socket, se riceve determinati messaggi cambierà runlevel.
Quindi puoi usare init
come rudimentale gestore di servizi se vuoi, ma il compito principale in questi giorni è mantenere getty
è disponibile in modo che un utente possa accedere e dare il via alle transizioni di runlevel.
Mi stavo solo chiedendo, quali attività svolge init per configurare il sistema per una semplice shell?
Tutto quello che vuoi. Su Debian, in ogni /etc/rcX.d
directory è un collegamento simbolico a uno script in /etc/init.d
e puoi personalizzare o rimuovere completamente quegli script. L'ordine viene stabilito facendo precedere ogni script da un 00
, 01
, ecc.
Puoi anche specificare un -b
opzione a init
(cioè tramite la riga di comando del kernel) se vuoi solo init
generare una conchiglia. Quando esci dalla shell, init
muore e quando init
muore, il kernel andrà nel panico.
Il minimo assoluto che init deve fare è eseguire almeno un altro programma e non uscire mai. Se init esce, il sistema va in crash. Suppongo che anche l'esecuzione di un altro programma non sia strettamente necessaria, ma se non lo fai init dovrebbe essere responsabile di fare tutto ciò che il sistema dovrebbe fare, altrimenti non sarebbe molto utile.