Skip to content

Cosa fa esattamente l'init?

Dopo aver consultato specialisti in questa materia, programmatori di diversi rami e professori, abbiamo trovato la soluzione alla domanda e la lasciamo riflessa in questo post.

Soluzione:

Sistema 5 init vi dirà solo una piccola parte della storia.

C'è una sorta di miopia che colpisce il mondo Linux. Le persone pensano di usare una cosa chiamata "System 5 init", e che questo sia il sistema tradizionale e il miglior punto di partenza. In realtà non è così.

La tradizione non è in realtà ciò che queste persone dicono che sia, tanto per cominciare. Sistema 5 init e Sistema 5 rc risalgono all'AT&T UNIX System 5, che era quasi altrettanto lontano dal primo UNIX di quanto lo siamo ora (diciamo) dalla prima versione di Linux-Mandrake.

La prima edizione di UNIX aveva solo init. Non aveva rc. Il linguaggio assembly della 1ª edizione init (il cui codice è stato restaurato e reso disponibile da Warren Toomey et al.) generava e respawnava direttamente 12 getty , ha montato 3 filesystem hardwired da una tabella incorporata e ha eseguito direttamente un programma dalla home directory di un utente chiamato mel. Il getty era anche direttamente nell'immagine del programma.

Un altro decennio dopo UNIX System 5 arrivò il cosiddetto sistema di init "tradizionale" di Linux. Nel 1992, Miquel van Smoorenburg (ri)scrisse un sistema di init per Linux. init+rce gli strumenti ad esso associati, a cui oggi ci si riferisce come "System 5 init", anche se in realtà non si tratta del software di UNIX System 5 (e non è semplicemente init).

Sistema 5 init/rc non è il miglior punto di partenza, e anche se si aggiunge la conoscenza di systemd non copre la metà di ciò che c'è da sapere. C'è stato molto lavoro nell'area della progettazione del sistema di init (per Linux e i BSD) solo negli ultimi due decenni. Ogni sorta di decisione ingegneristica è stata discussa, presa, progettata, implementata e messa in pratica. Anche le Unice commerciali hanno fatto molto.

Sistemi esistenti da studiare e da cui imparare

Ecco un elenco incompleto di alcuni dei principali sistemi init diversi da questi due, e uno o due dei loro (numerosi) punti salienti:

  • Finit di Joachim Nilsson ha scelto di utilizzare un file di configurazione più leggibile.
  • Il minit di Felix von Leitner ha optato per un sistema di configurazione basato su un filesystem che è il database, per una memoria di dimensioni ridotte e per le dipendenze start/stop, tra le quali init inizia.
  • Runit di Gerrit Pape ha scelto quello che ho descritto in precedenza come lo spawn di quattro script di shell ... l'approccio.
  • InitNG mirava ad avere dipendenze, obiettivi con nome, file di configurazione multipli e una sintassi di configurazione più flessibile con un sacco di impostazioni in più per i processi figli.
  • upstart ha optato per una riprogettazione completa, modellando il sistema non come servizi e interdipendenze, ma come eventi e lavori innescati da essi.
  • Il progetto di nosh include l'espulsione di tutta la gestione dei servizi (compreso il sistema di gestione dei servizi di nosh). getty e la raccolta degli zombie) in un gestore di servizi separato e solo gestire dispositivi/symlink/directory ed eventi di sistema "API" specifici del sistema operativo.
  • sinit è un init molto semplice. Esegue /bin/rc.init il cui compito è avviare i programmi, montare il filesystem, ecc. Per questo si può usare qualcosa come minirc.

Inoltre, circa 10 anni fa, c'è stata una discussione tra gli utenti di daemontools e altri sull'uso di svscan come processo 1, il che ha portato a progetti come lo studio di Paul Jarc su svscan come processo 1, alle idee di Gerrit Pape e a svscan come processo 1 di Laurent Bercot.

Il che ci porta a ciò che fanno i programmi del processo n. 1.

Cosa fanno i programmi del processo 1

Le nozioni su ciò che il processo #1 "dovrebbe" fare sono per loro natura soggettive. Una nozione significativa oggettivo criterio di progettazione è quello che il processo #1 deve almeno fare. Il kernel gli impone diversi requisiti. E ci sono sempre alcune cose specifiche del sistema operativo di vario tipo che deve fare. Quando si tratta di ciò che il processo #1 deve tradizionalmente fatto, allora non siamo a quel minimo e non lo siamo mai stati.

Ci sono diverse cose che i kernel dei sistemi operativi e altri programmi richiedono al processo n. 1 a cui non si può sfuggire.

La gente vi dirà che fork()e che agire come genitore di processi orfani è la funzione principale del processo #1. Ironicamente, questo non è vero. Gestire i processi orfani è (con i recenti kernel Linux, come spiegato all'indirizzo https://unix.stackexchange.com/a/177361/5132) una parte del sistema che si può in gran parte escludere dal processo n. 1 per passare ad altri processi, come ad esempio un processo dedicato a . gestore di servizi. Tutti questi sono gestori di servizi che vengono eseguiti al di fuori del processo #1:

  • l'IBM AIX srcmstr programma, il controllore delle risorse di sistema
  • Gerrit Pape runsvdir da runit
  • Daniel J. Bernstein svscan da daemontools, di Adam Sampson svscan da freedt, di Bruce Guenter svscan da daemontools-encore, e il metodo di Laurent Bercot s6-svscan da s6
  • Wayne Marshall perpd da perp
  • la Struttura di gestione dei servizi in Solaris 10
  • il service-manager da nosh

Allo stesso modo, come spiegato in https://superuser.com/a/888936/38062, l'insieme /dev/initctl non ha bisogno di essere vicino al processo #1. Ironicamente, è il systemd altamente centralizzato che dimostra che può essere spostato fuori dal processo #1.

Al contrario, le cose obbligatorie per init, che la gente di solito dimentica nei propri progetti "fuori di testa", sono cose come la gestione di SIGINT, SIGPWR, SIGWINCHe così via inviati dal kernel e l'esecuzione delle varie richieste di modifica dello stato del sistema inviate dai programmi che "sanno" che certi segnali al processo #1 significano certe cose. (Per esempio: Come spiegato all'indirizzo https://unix.stackexchange.com/a/196471/5132, i toolset BSD "sanno" che SIGUSR1 ha un significato specifico).

Ci sono anche compiti di inizializzazione e finalizzazione che non si possono evitare, o che soffrirebbero molto se non venissero eseguiti, come il montaggio di filesystem "API" o il lavaggio della cache del filesystem.

Le basi del trattamento dei filesystem "API" sono poco diverse da quelle del funzionamento di init UNIX della 1a edizione: si ha un elenco di informazioni integrate nel programma, e si può semplicemente mount()tutte le voci dell'elenco. Questo meccanismo si trova in sistemi diversi come BSD (sic!) init, attraverso il nosh system-manager, fino a systemd.

"impostare il sistema per una semplice shell".

Come avete osservato, init=/bin/sh non riesce a far montare i file system "API", si blocca in modo sgraziato e senza il flush 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 capire che cosa non si può fare nei programmi del processo #1, e quindi per mettere sulla buona strada il proprio obiettivo di progettazione, la cosa migliore è osservare le sovrapposizioni nel funzionamento del runit di Gerrit Pape, del minit di Felix von Leitner e del programma system-manager del pacchetto nosh. I primi due mostrano due tentativi di essere minimalisti, pur gestendo le cose che è impossibile evitare.

Quest'ultimo è utile, a mio avviso, per la sua ampia voce di manuale per il programma system-manager che descrive esattamente quali filesystem "API" vengono montati, quali operazioni di inizializzazione vengono eseguite e quali segnali vengono gestiti.ed; in un sistema che per progettazione ha il gestore del sistema che si limita a generare altre tre cose (il gestore dei servizi, un logger di accompagnamento e il programma per eseguire i cambiamenti di stato) e a fare l'inevitabile solo nel processo #1.

System V init su Debian (ci sono altre varianti e variazioni) fa quanto segue:

  • Quando entra in un livello di esecuzione, chiama gli script in /etc/rcX.d/S* in ordine alfanumerico, dove X è il runlevel. Questi script devono configurare il runlevel. L'impostazione tipica consiste nell'avviare i demoni e nell'eseguire le attività di configurazione per quel livello di esecuzione. Si tratta di un'operazione da eseguire una sola volta quando si entra nel runlevel.
  • Quando si è in un livello di esecuzione, si avviano i demoni elencati nella cartella /etc/inittab che devono essere attivi durante quel livello di esecuzione. Se questi demoni smettono di funzionare, li riavvia. Sebbene sia possibile far gestire qualsiasi demone da init, come minimo si vogliono alcuni demoni gettyin modo da potersi loggare. getty esce una volta completato il login, poi init lo riavvia, fornendo un nuovo prompt di login.
    • Se il demone si riavvia troppe volte in un tempo troppo breve, smette di provare a riavviarlo per un po'.
    • Il fatto che qualcosa sia stato avviato dagli script di kickoff quando si entra nel livello di esecuzione non fa sì che init cerchi automaticamente di mantenerlo in esecuzione. È necessario specificarlo separatamente nell'opzione /etc/inittab.
  • Quando si esce da un livello di esecuzione, vengono richiamati gli script in /etc/rcX.d/K* in ordine alfanumerico, dove X è il livello di esecuzione. Un modo per implementare lo spegnimento o il riavvio è quello di definire un runlevel per questi eventi e rendere l'ultimo task eseguito il livello halt o reboot e il comando halto reboot.
  • Richiama gli eseguibili in risposta a determinati eventi, come gli eventi di alimentazione o Ctrl-Alt-Del.
  • Ascolta un socket, se riceve determinati messaggi cambia livello di esecuzione.

È quindi possibile utilizzare init come rudimentale gestore di servizi, se si vuole, ma il suo compito principale in questi giorni è quello di mantenere gettyin modo che un utente possa effettuare il login e dare il via alle transizioni di runlevel.

Mi stavo chiedendo, quali compiti svolge init per impostare il sistema per una semplice shell?

Qualsiasi cosa si voglia. Su Debian, in ogni /etc/rcX.d c'è un link simbolico a uno script in /etc/init.d ed è possibile personalizzare o rimuovere completamente tali script. L'ordine viene stabilito precedendo ogni script con un 00, 01, ecc.

È inoltre possibile specificare un -b a init (ad esempio tramite la riga di comando del kernel) se si vuole solo che init avvii una shell. Quando si esce dalla shell, init muore e quando init muore, il kernel va in panico.

Il minimo indispensabile che init deve fare è eseguire almeno un altro programma e non uscire mai. Se init esce, il sistema si blocca. Suppongo che anche l'esecuzione di un altro programma non sia strettamente necessaria, ma se non lo si facesse l'init dovrebbe essere responsabile di fare ogni cosa che ci si aspetta che il sistema faccia, altrimenti non sarebbe molto utile.

Recensioni e valutazioni della guida

Se hai qualche incertezza e capacità di sviluppare la nostra affermazione puoi fare un'interpretazione e la analizzeremo con desiderio.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.