Was genau macht init?

43

Ich erstelle eine Linux-Distribution und brauche jetzt ein Init-Programm. Ich kann sehr gut in c programmieren und kenne mich ziemlich gut mit Linux aus (nicht sehr viel, aber ich verwende Arch Linux seit 4 Jahren für die Entwicklung). Deshalb dachte ich, ich sollte versuchen, mein eigenes Init-Skript in C zu schreiben Ich frage mich nur, welche Aufgaben hat init, um das System für eine einfache Shell einzurichten? (Wenn ich frage "Was macht init?", Weiß ich, was init ist und wofür es ist. Ich weiß nur nicht, welche Aufgaben es tut.)

Ich brauche Code nicht und ich tun , möglicherweise nicht einmal brauchen grundlegende Befehle , aber ich kann die Reihenfolge müssen , dass sie in ausgeführt werden .

DividedByZero
quelle
1
Sie können einen beliebigen Interpreter für Init-Skripte im SysV-Stil verwenden, einschließlich Perl, awk, bash, (t) csh, native Binärdateien, ... Bash wird normalerweise verwendet, da praktisch garantiert ist, dass es auf dem System verfügbar ist, auf dem sich solche Skripte befinden Wird zum relevanten Zeitpunkt des Startvorgangs bereitgestellt, nicht weil eine gewisse Kopplung zwischen SysVinit und bash besteht. SysVinit definiert den Vertrag und es steht jedem Skript frei, diesen Vertrag so zu implementieren, wie es der Entwickler für richtig hält.
CVn

Antworten:

53

System 5 initwird Ihnen nur einen kleinen Teil der Geschichte erzählen.

Es gibt eine Art Kurzsichtigkeit, die die Linux-Welt betrifft. Die Leute denken, dass sie ein Ding namens "System 5 init" verwenden, und das ist sowohl das, was traditionell ist, als auch der beste Ausgangspunkt. Weder ist in der Tat der Fall.

Tradition ist eigentlich nicht das, was solche Leute sagen. System 5 initund System 5 rcdatieren auf AT & T UNIX System 5, das fast so weit nach dem ersten UNIX war, wie wir es jetzt (etwa) nach der ersten Version von Linux-Mandrake sind.

Erstausgabe hatte nur UNIX init. Es hatte nicht rc. Die erste Ausgabe der Assemblersprache init( Code derer wurde restauriert und zur Verfügung gestellt von Warren Toomey et al. ) Direkt hervorgebracht und respawned 12 gettyProzesse, 3 montiert fest verdrahtet Dateisysteme von einem eingebauten Tisch und lief ein Programm direkt aus dem Home - Verzeichnis einer benutzername mel. Die gettyTabelle befand sich auch direkt im Programmabbild.

Es war ein weiteres Jahrzehnt nach UNIX System 5, als das sogenannte "traditionelle" Linux-Init-System auf den Markt kam. 1992 schrieb Miquel van Smoorenburg ein Linux init+ rcund die dazugehörigen Tools (neu), die heute als "System 5 init" bezeichnet werden, obwohl es sich eigentlich nicht um die Software von UNIX System 5 handelt (und das nicht nur) init).

System 5 init/ rcist nicht der beste Ausgangspunkt, und selbst wenn man Kenntnisse über systemd hinzufügt, die nicht die Hälfte des Wissens abdecken. Auf dem Gebiet des Init-Systemdesigns (für Linux und die BSDs) wurde allein in den letzten zwei Jahrzehnten viel Arbeit geleistet. Alle möglichen technischen Entscheidungen wurden diskutiert, getroffen, entworfen, implementiert und umgesetzt. Auch die Commercial Unices haben viel getan.

Bestehende Systeme zum Lernen und Lernen

Hier ist eine unvollständige Liste einiger der wichtigsten Init-Systeme außer diesen beiden und einem oder zwei ihrer (mehreren) hervorstechenden Punkte:

  • Joachim Nilsson finit ging die Route der eine für Menschen lesbare Konfigurationsdatei.
  • Felix von Leitners Ziel war ein Dateisystem-ist-die-Datenbank-Konfigurationssystem, ein kleiner Speicherbedarf und Start / Stopp-Abhängigkeiten, unter anderem, wenn es initlosgeht.
  • Gerrit Papes Runit ging auf das über, was ich zuvor als den Ansatz mit nur vier Spawn-Shellskripten beschrieben habe .
  • InitNG zielte darauf ab, Abhängigkeiten, benannte Ziele, mehrere Konfigurationsdateien und eine flexiblere Konfigurationssyntax mit einer ganzen Reihe von Einstellungen für untergeordnete Prozesse zu haben.
  • upstart entschied sich für eine komplette Neugestaltung und modellierte das System nicht als Dienste und Abhängigkeiten, sondern als von ihnen ausgelöste Ereignisse und Jobs.
  • Das Design von nosh beinhaltet, dass das gesamte Service-Management (einschließlich des Laichens und Erntens von gettyZombies) in einen separaten Service-Manager verlagert wird und nur betriebssystemspezifische "API" -Geräte / Symlinks / Verzeichnisse und Systemereignisse verarbeitet werden.
  • sinit ist eine sehr einfache Init. Es führt aus, /bin/rc.initwessen Aufgabe es ist, Programme zu starten, das Dateisystem zu mounten usw. Hierfür können Sie so etwas wie minirc verwenden .

Darüber hinaus gab es vor ungefähr 10 Jahren eine Diskussion unter Daemontools-Anwendern und anderen über die Verwendung svscanals Prozess 1, die zu Projekten wie Paul Jarcs Svscan als Prozess 1-Studie , Gerrit Papes Ideen und Laurent Bercots Svscan als Prozess 1 führte .

Das bringt uns zu dem, was die Programme von Prozess 1 leisten.

Welchen Prozess # 1 Programme tun

Vorstellungen davon, was der Prozess Nr. 1 "tun soll", sind ihrer Natur nach subjektiv. Ein aussagekräftiges objektives Entwurfskriterium ist das, was Prozess 1 mindestens leisten muss . Der Kernel stellt verschiedene Anforderungen an ihn. Und es gibt immer einige betriebssystemspezifische Dinge verschiedener Art, die es zu tun hat. Wenn es darum geht, was Prozess Nr. 1 traditionell getan hat, dann sind wir nicht bei diesem Minimum und haben es nie wirklich getan.

Es gibt einige Dinge, die verschiedene Betriebssystemkerne und andere Programme von Prozess 1 verlangen, denen man sich einfach nicht entziehen kann.

Die Leute werden Ihnen sagen, dass fork()die Hauptfunktion von Prozess 1 darin besteht , Dinge zu erledigen und als Eltern verwaister Prozesse zu agieren. Ironischerweise ist das nicht wahr. Der Umgang mit verwaisten Prozessen ist (bei neueren Linux-Kerneln, wie unter https://unix.stackexchange.com/a/177361/5132 erläutert ) ein Teil des Systems, den man in anderen Prozessen, wie z ein engagierter Service-Manager . All dies sind Service-Manager, die nicht mit Prozess 1 konfrontiert sind:

  • das IBM AIX- srcmstrProgramm, der System Resource Controller
  • Gerrit Pape ist runsvdirvon runit
  • Daniel J. Bernstein svscanvon daemontools, Adam Sampson svscanvon freedt , Bruce Guenter svscanvon daemontools-encore und Laurent Bercot s6-svscanvon s6
  • Wayne Marshall ist perpdvon perp
  • die Service Management Facility in Solaris 10
  • das service-managervon nosh

Ebenso muss, wie unter https://superuser.com/a/888936/38062 erläutert , die gesamte /dev/initctlIdee nicht in der Nähe von Prozess 1 liegen. Ironischerweise ist es das stark zentralisierte System, das zeigt, dass es aus Prozess 1 herausbewegt werden kann.

Umgekehrt ist für die obligatorischen Dinge init, in der Regel , dass die Menschen in ihrem off-the-top-of-the-Kopf - Design vergessen, sind Dinge wie Handhabung SIGINT, SIGPWR, SIGWINCHund so weiter aus dem Kernel gesendet und die verschiedenen Systemstatusänderungsanforderungen erlassen gesendet von Programmen, die "wissen", dass bestimmte Signale, um # 1 zu verarbeiten, bestimmte Dinge bedeuten. (Zum Beispiel: Wie unter https://unix.stackexchange.com/a/196471/5132 erläutert , "wissen" BSD-Toolsets, dass SIGUSR1sie eine bestimmte Bedeutung haben.)

Es gibt auch einmalige Initialisierungs- und Finalisierungsaufgaben, denen man sich nicht entziehen kann oder die sehr unter Umständen nicht ausgeführt werden, z. B. das Mounten von "API" -Dateisystemen oder das Leeren des Dateisystem-Cache.

Die Grundlagen des Umgangs mit "API" -Dateisystemen unterscheiden sich kaum von der Funktionsweise von initUnix der ersten Edition: Man hat eine Liste mit Informationen, die fest im Programm verankert sind, und man hat einfach mount()alle Einträge in der Liste. Sie werden diesen Mechanismus in Systemen finden, die so unterschiedlich sind wie BSD (sic!) init, Von nosh system-managerbis systemd.

"Richten Sie das System für eine einfache Shell ein"

Wie Sie bereits bemerkt haben, werden init=/bin/sh"API" -Dateisysteme nicht gemountet, stürzen in ungünstiger Weise ohne Cache-Flush ab, wenn ein Typ exit( https://unix.stackexchange.com/a/195978/5132 ) eingibt , und lassen es im Allgemeinen an den (Super-) Benutzer, die Aktionen, die das System minimal nutzbar machen, manuell durchzuführen.

Um zu sehen, was man eigentlich keine andere Wahl hat, als in den Programmen Nr. 1 zu arbeiten, und Sie so auf einen guten Kurs für Ihr erklärtes Designziel zu bringen, ist es Ihre beste Option, die Überschneidungen in der Funktionsweise von Gerrit Papes runit, Felix von, zu untersuchen Leitners Minit und das system-managerProgramm aus dem Nosh-Paket. Die beiden ersteren zeigen zwei Versuche, minimalistisch zu sein und dennoch mit den Dingen umzugehen, die man nicht vermeiden kann.

Letzteres ist nützlich, ich schlage vor, für seine umfangreiche manuelle Eingabe für das system-managerProgramm, die genau angibt, welche "API" -Dateisysteme eingehängt sind, welche Initialisierungsaufgaben ausgeführt werden und welche Signale behandelt werden; in einem System , das durch Design der Systemmanager nur laichen drei andere Dinge (die Service - Manager, ein Begleitlogger und das Programm ausführen , um die Zustandsänderungen) und nur tun , um die unvermeidlich in Prozess # 1 hat.

JdeBP
quelle
3
Super Antwort und sehr informativ. Aber ich frage mich, wo in diesem großen Zusammenhang OSX ist launchd. Manchmal vergessen die Leute gänzlich, dass OSX ein (großartiges) Mitglied der großen * nix-Familie ist.
DavAlPi
4

System V init unter Debian (es gibt andere Varianten und Variationen) führt Folgendes aus:

  • Bei der Eingabe eines Runlevels werden Skripte /etc/rcX.d/S*in alphanumerischer Reihenfolge aufgerufen, wobei Xes sich um den Runlevel handelt. Diese Skripte sollten den Runlevel einrichten. Das typische Setup startet Daemons und führt Setup-Aufgaben für diese Ausführungsebene aus. Dies ist eine einmalige Aktion, wenn Sie das Runlevel betreten.
  • Während der Ausführung werden Daemons gestartet, die in der Liste /etc/inittabals aktiv aufgeführt sind und während dieser Ausführung aktiv sein müssen. Wenn diese Daemons nicht mehr ausgeführt werden, werden sie neu gestartet. Während Sie einen beliebigen Dämon verwalten lassen können, benötigen Sie initmindestens einige getty, damit Sie sich anmelden können. gettyWird nach Abschluss der Anmeldung beendet und anschließend initneu gestartet, wobei eine neue Anmeldeaufforderung angezeigt wird.
    • Wenn der Dämon zu oft in zu kurzer Zeit neu gestartet wird, wird für eine Weile nicht mehr versucht, ihn neu zu starten.
    • Nur weil etwas von den Kickoff-Skripten beim Aufrufen der Ausführungsebene gestartet wurde, wird nicht initautomatisch versucht, es am Laufen zu halten. Sie müssen dies separat in der Tabelle angeben /etc/inittab.
  • Beim Verlassen eines Runlevels werden Skripte /etc/rcX.d/K*in alphanumerischer Reihenfolge aufgerufen, wobei Xder Runlevel angegeben ist. Eine Möglichkeit zum Implementieren des Herunterfahrens oder Neustarts besteht darin, einen Runlevel für diese Ereignisse zu definieren und die letzte ausgeführte Task zum Befehl haltoder zu machen reboot.
  • Es ruft ausführbare Dateien als Antwort auf bestimmte Ereignisse auf, z. B. Energieereignisse oder Strg-Alt-Entf.
  • Es lauscht an einem Socket. Wenn es bestimmte Nachrichten empfängt, ändert es den Runlevel.

Sie können also initals rudimentärer Service-Manager fungieren, aber es ist heutzutage die Hauptaufgabe, die gettyverfügbaren zu behalten , damit sich ein Benutzer anmelden und Runlevel-Übergänge starten kann.

Ich habe mich nur gefragt, welche Aufgaben hat init, um das System für eine einfache Shell einzurichten?

Irgendwas du willst. Unter Debian befindet sich in jedem /etc/rcX.dVerzeichnis ein Symlink zu einem Skript, /etc/init.dund Sie können diese Skripte vollständig anpassen oder entfernen. Die Reihenfolge wird durch vor jedem Skript mit einem etablierten 00, 01usw.

Sie können auch eine -bOption angeben init(z. B. über die Kernel-Befehlszeile), wenn Sie nur initeine Shell erzeugen möchten . Wenn Sie die Shell verlassen, initstirbt und wenn initstirbt, gerät der Kernel in Panik.

LawrenceC
quelle
2

Das absolute Minimum, das init tun muss, ist, mindestens ein anderes Programm auszuführen und es niemals zu beenden. Wenn init beendet wird, stürzt das System ab. Ich nehme an, dass das Ausführen eines anderen Programms nicht unbedingt erforderlich ist, aber wenn Sie dies nicht tun, müsste init dafür verantwortlich sein, alles zu tun, was vom System erwartet wird, oder es wäre nicht sehr nützlich.

hildred
quelle
1
Ich hatte fehlerhafte Linux-Systeme, auf denen PID 1 abgestürzt ist, aber das System lief im Grunde weiter. Wie schlimm ein Absturz von PID 1 ist, hängt möglicherweise von der Kernel-Version ab.
Gilles 'SO- hör auf böse zu sein'
1

init kann machen was du willst

init ist eine beliebige ausführbare Datei, die vom Linux-Kernel am Ende des Startvorgangs aufgerufen wird (und die einzige solche ausführbare Datei).

Es wird normalerweise als ausführbare ELF-Datei implementiert, kann aber auch ein Shell-Skript mit chmod +x: Init als Shell-Skript sein

Typische Implementierungen wie sysemd lesen Konfigurationsdateien /etc/initrcund geben dann eine Reihe von Userland-Prozessen aus, die auf diesen Konfigurationen basieren, um verschiedene Aspekte des Systems zu implementieren.

Dies ist jedoch vollständig implementierungsspezifisch. Daher kann Ihre Frage nicht beantwortet werden, ohne eine bestimmte Implementierung anzugeben. Ich habe zum Beispiel mit einem initProzess gespielt, der einfach einen rebootSystemaufruf für Bildungszwecke ausführt.

Der Linux-Kernel sucht /initstandardmäßig nach der ausführbaren Datei im Pfad , diese kann jedoch mit dem init=Befehlszeilenparameter des Linux-Kernels überschrieben werden.

Eine großartige Möglichkeit zum Herumspielen initist die Verwendung von QEMU, da Sie die Kernel-Befehlszeilenparameter mit der -appendOption von der QEMU-Befehlszeile an QEMU übergeben können , ohne befürchten zu müssen, Ihren Desktop zu beschädigen.

Hier ist mein minimales vollautomatisches Buildroot + QEMU-Setup , das es sehr einfach macht, mit Ihren eigenen Inits herumzuspielen, um die Angelegenheit zu entmystifizieren.

Ciro Santilli ist ein Schauspieler
quelle
0

Wenn Sie sich dem modularen Prinzip "Mach eins und mach es gut" verschrieben haben, initsollte ein Programm Prozesse starten.

Prozesse starten

Sie sollte ausgeführt werden, sobald der Kernel erfolgreich dekomprimiert wurde, und sich um alle grundlegenden Aufgaben kümmern, die mit der Initialisierung aller anfänglichen Prozesse verbunden sind, die ein System zum Betrieb benötigt (z. B. das Mounten von Laufwerken in / etc / fstab, das Aufrufen von Netzwerkschnittstellen und bald).

Da der Vorgang des Hochfahrens und Herunterfahrens im Wesentlichen umgekehrt ist, stellt ein Init-Programm häufig auch sicher, dass Prozesse bei einem Befehl zum Herunterfahren gestoppt werden.

Prozesse stoppen

Dies bedeutet, dass Prozesse gemäß der Manpage dieses Prozesses gestoppt werden müssen (mit anderen Worten, nicht nur ein offensichtlicher kill -9Prozess, sondern der Prozess sollte so heruntergefahren werden, wie er beendet werden soll), die Bereitstellung von Laufwerken aufgehoben und schließlich der endgültige Befehl zum Herunterfahren ausgegeben werden muss .

Verweise

Eine gute Referenz dafür, wie dies von anderen gemacht wird, sind die /etc/rc.d-Skripte von Slackware und ein einfaches Init-System, das bereits existiert, wie ninit (ein Nachfolger von minit). Es verfügt über eine Prozessüberwachung (dh, wenn ein Prozess stirbt, wird er neu gestartet), was wohl nicht die Aufgabe von init ist, aber dennoch recht einfach und verständlich ist, insbesondere anhand der Beispielskripte des Autors.

Klaatu von Schlacker
quelle