Wie werden PIDs generiert?

42

Unter * nix sind PIDs eindeutige Bezeichner für ausgeführte Prozesse. Wie werden PIDs generiert? Ist es nur eine ganze Zahl, die inkrementiert wird, oder eine komplexere Struktur wie eine Liste? Wie werden sie recycelt? Mit Recycling meine ich, dass wenn ein Prozess endet, seine PID irgendwann von einem anderen Prozess wiederverwendet wird.

Giovanni Funchal
quelle

Antworten:

39

Wie Wikipedia sagt,

Unter Unix werden Prozess-IDs normalerweise sequenziell vergeben, beginnend bei 0 und bis zu einem Maximalwert, der von System zu System unterschiedlich ist. Sobald diese Grenze erreicht ist, wird die Zuordnung bei Null neu gestartet und erneut erhöht. Für diesen und nachfolgende Durchläufe werden jedoch alle PIDs, die noch Prozessen zugewiesen sind, übersprungen.

Es ist also wirklich eine sehr einfache Richtlinie für "Generieren", nur Erhöhen eines Zählers und "Wiederverwenden". Bringen Sie die Zahl einfach auf einen Maximalwert und erhöhen Sie sie so lange, bis Sie eine Zahl finden, die einem abgeschlossenen und abgeschlossenen Prozess zugewiesen wurde wurde aus der Prozesstabelle entfernt.

Einige Unix-Implementierungen wie AIX verwenden eine weniger einfache Richtlinie, siehe z . B. diese FAQ .

Alex Martelli
quelle
Danke für die Antwort. Was ist eigentlich genau diese AIX-Richtlinie, die weniger einfach ist?
1
@Helltone, ich glaube nicht, dass AIX genau dokumentiert, welche Richtlinie verwendet wird (sie kann sich also bei jedem Release ändern), aber Sie können sich das als Zufallszahlengenerierung im entsprechenden Bereich vorstellen (die wiederholt wird, bis eine PID generiert wird, die das ist derzeit nicht in Gebrauch).
Alex Martelli
Dieser Algorithmus scheint mir ein bisschen problematisch zu sein. Wie stellen Sie sicher, dass Sie nicht in eine Sackgasse geraten? Und gibt es kein Leistungsproblem?
1
Der Kernel hat die Kontrolle und muss nichts sperren. Wie kann es also zu einem Deadlock kommen? Ja, es ist ein geringer Preis für die Leistung zu zahlen (ein kleiner Mehraufwand zur Gabelzeit - sagen wir ein paar Dutzend Maschinenanweisungen für einen kongruenten PRNG- oder / dev / urandom-Lesevorgang, verglichen mit viel weniger für ein Gegeninkrement), aber das ist immer so Dies gilt für Maßnahmen zur Verbesserung der Sicherheit (überprüfen Sie beispielsweise den CPU-Overhead der HTTPS-Kommunikation im Vergleich zu einfachem HTTP ;-).
Alex Martelli
Ich meinte livelock ( while(true);), sorry, ich habe schnell
11

Es variiert.

Die meisten Systeme führen einfach eine Zählung der zuletzt generierten PID durch, addieren eine (Zeilenumbruch bei einer maximalen Zahl wie 65535 oder etwas kleiner - häufig erfolgt der Zeilenumbruch bei 65000 oder sogar 60000) und überprüfen, ob die Zahl derzeit nicht verwendet wird ( Wiederholen, wenn die PID noch verwendet wird - PID 1, der Kernel, ist also noch vorhanden und wird nicht erneut ausgegeben.

Andere sicherheitsorientierte Systeme generieren eine zufällige Zahl und prüfen, ob sie nicht verwendet wird.

Zu jedem Zeitpunkt ist garantiert, dass alle PID-Nummern eindeutig sind.

Jonathan Leffler
quelle
9

In Bezug auf den Recycling-Teil der Frage ist zu beachten, dass eine PID nicht verfügbar ist, sobald der Prozess mit dieser PID endet. Die pid wird erst verfügbar, wenn das übergeordnete Element dieses Prozesses den Beendigungsstatus seines untergeordneten Elements über eine Form des wait () - Systemaufrufs erfasst. Ein Kind, das gekündigt wird, dessen Eltern aber nicht gewartet haben, wird als Zombie bezeichnet und in der Regel in einem PS als nicht mehr gültig angezeigt. Es ist möglich, dass ein Elternteil, der sich schlecht benimmt, das Pidensystem aushungert, wenn es Kinder startet und nicht () auf sie wartet.

Wenn das übergeordnete Element eines Prozesses stirbt, bevor es den Status eines untergeordneten Elements erfasst, ist dies in Ordnung. Das Kind wird von init geerbt, der dafür sorgt, dass wait () ausgegeben und die pid recycelt wird.

frankc
quelle
Dies ist ein sehr wichtiges Detail. Ohne es wäre sogar eine einfache myprog &gefolgt von wait $!UB.
Andreas
3

Es handelt sich um Sequenznummern, die (mit einem betriebssystemspezifischen Wert) umbrochen werden, wenn das System lange genug in Betrieb ist. Zahlen werden nie wiederverwendet, es sei denn, sie sind zum Zeitpunkt von frei fork().

Donal Fellows
quelle