Clause
← Gesamte Dokumentation

Übersetzt aus dem englischen Original · 1e3a39c8-dirty · 2026-10-26 · Auf Englisch lesen

Prozesse

Executor

Eine Runtime führt ihre Prozesse auf ihren Scheduler-Workern aus (Worker, Ausführungsmodell). Beim Start wird der Aufruf der Einstiegsfunktion zum ersten Prozess, dem Hauptprozess, und der Executor läuft, bis dieser endet:

Worker

Der Executor führt Prozesse auf RuntimeOptions::schedulers Worker-Threads aus: dem Thread, der das Programm gestartet hat, und je einem weiteren Thread pro zusätzlichem Worker. Programme übernehmen die Anzahl aus --schedulers N (1 bis 1.024, Runtime-Optionen); Standard ist ein Worker pro logischem Prozessor, auf dem das Programm laufen darf (seiner Affinitätsmaske, wie die Online-Scheduler von OTP), oder pro CPU aus --scheduler-cpus.

Aufwecken und Herunterfahren brauchen keinen weiteren Mechanismus, weil jede Änderung am Scheduling-Zustand eines Prozesses unter dem Executor-Mutex geschieht:

CPU-Bindung

Worker sind standardmäßig ungebunden: Das Betriebssystem platziert sie auf beliebigen CPUs der Affinitätsmaske des Programms, wie beim Standard +sbt u von OTP. --scheduler-cpus SET (Runtime-Optionen) bindet Worker N an die N-te CPU der Menge, bei mehr Workern reihum, wie +sbt/+sct von OTP; die Timer- und I/O-Threads bleiben ungebunden.

Empfangs-Timeouts

Timer liegen in einem hierarchischen gehashten Timer-Rad (timer wheel), wie ERTS sie führt (scheduler/timer_wheel):

Exits

Ein Prozess außer dem Hauptprozess endet mit einem Exit-Grund, wie in OTP (detail::exit_reason, process/exits). Exit-Signale tragen ihn zu verlinkten Prozessen (Links) und 'DOWN'-Nachrichten zu überwachenden (Monitore); Fehlerberichte zeigen ihn.

Wie der Prozess endetExit-GrundFehlerbericht
Sein erster Aufruf kehrt zurücknormalKeiner
exit(Reason) (auch normal, kill)ReasonKeiner
Ein Fehler (error/1,2,3, badarith, {badmatch, V}, undef, ...){Reason, Stack}Ja
Ein nicht abgefangenes throw(Value){{nocatch, Value}, Stack}Ja
Ein Exit-Signal beendet ihn (Exit-Signale)Der Grund des Signals, killed für exit(Pid, kill)Keiner

Ein Fehlerbericht wird auf stderr geschrieben, wenn der Prozess endet, nach dem Leeren der Standardausgabe, im Format des Standard-Logger-Handlers von OTP:

=ERROR REPORT==== 8-Oct-2026::03:42:15.983000 ===
Error in process <0.8.0> with exit value:
{boom,[{crash_reports,'-main/1-fun-6-',0,[]}]}

Der Kopf enthält die Ortszeit; der Grund wird so gesetzt, wie ~p es tut. Der Hauptprozess schreibt keinen: Seine nicht abgefangene Ausnahme ist die des Programms (ausführbare Dateien).

Nachrichten

Dest ! Msg und erlang:send(Dest, Msg) werten zuerst Dest aus und geben Msg zurück.

DestWirkung
Eine Pid eines lebenden ProzessesMsg wird flach in den Heap des Empfängers kopiert (Kopieren zwischen Heaps), wie OTP Nachrichten kopiert, eine große in einen Block, den der Empfänger übernimmt (Nachrichtenübergabe), und an seinen Signal-Eingang angehängt; bei einem Empfänger, der auf einem anderen Worker läuft, in einen Puffer unter seinen Eingängen, den er beim nächsten Nachsehen übernimmt (Eingangspuffer)
Eine Pid eines beendeten ProzessesNichts; die Sendung gelingt
Ein registrierter NameWie für seine Pid; badarg, wenn kein lebender Prozess den Namen hat
{Name, nonode@nohost} aus zwei AtomenWie für die als Name registrierte Pid; nichts, wenn es keine gibt
{Name, Node} für jeden anderen KnotenNichts (es gibt keine anderen Knoten)
Eine ReferenzWie für den Besitzer eines aktiven Alias; sonst nichts
Alles anderebadarg

Eingangspuffer

Eine Sendung an einen Prozess, der auf einem anderen Worker läuft, nimmt überhaupt keine Sperre (Prozesserzeugung und -abbau):

Receive

receive wählt wie case unter seinen Klauseln aus, über die Nachrichten der Mailbox:

Ein Link verbindet zwei Prozesse in beide Richtungen (Signals in jedem Kontext: die verlinkten Pids in Link-Reihenfolge und das Flag trap_exit).

Monitore

Ein Monitor ist einseitig: Der überwachende Prozess hält ihn (per Referenz, in Signals), und der überwachte Prozess bewahrt die Referenz und die überwachende Pid, damit er die Nachricht senden kann, wenn er endet.

Registrierte Namen

Der Executor führt eine Tabelle von Namen (Atomen) zu Pids, und jeder Prozess seinen eigenen Namen (Signals::name).

Prozess-Dictionary

put/2, get/0,1, get_keys/0,1 und erase/0,1 verhalten sich wie bei OTP: put/2 und erase/1 geben den vorherigen Wert oder undefined zurück, erase/0 gibt jedes {Key, Value} zurück und leert das Dictionary, Schlüssel werden mit exakter Gleichheit gematcht (1 und 1.0 sind zwei Schlüssel).

Timer

start_timer/3,4 und send_after/3,4 (builtins/erlang/timers.cpp, scheduler/timers.cpp) schalten einen Timer im Rad des Executors scharf (dem, das die Empfangs-Timeouts verwenden), der beim Auslösen Msg oder {timeout, TimerRef, Msg} an eine Pid oder einen registrierten Namen sendet.

Introspektion

process_info/1,2 (builtins/erlang/introspection.cpp, scheduler/introspection.cpp) liest einen anderen Prozess unter der Sperre des Executors und kopiert seine Terme (Nachrichten, Dictionary) in den Heap des Aufrufers; ein Prozess, der auf einem anderen Worker läuft, wird gelesen, sobald seine Zeitscheibe endet. Eine Pid ohne lebenden Prozess ergibt undefined.

Spawn-Optionen

Quellen: builtins/erlang/spawning.cpp, scheduler/aliases.cpp.

Aliase

Ein Alias ist eine Referenz, an die Nachrichten gesendet werden können (Alias ! Msg): alias/0,1 (explicit_unalias oder reply für eine Nachricht) oder ein Monitor, der mit {alias, explicit_unalias | demonitor | reply_demonitor} von monitor/3 erzeugt wurde (demonitor endet mit dem Monitor, reply_demonitor beendet bei seiner ersten Nachricht auch den Monitor). unalias/1 beendet einen Alias des Aufrufers. Eine Sendung an eine Referenz, die kein aktiver Alias ist oder deren Besitzer geendet hat, wird verworfen. Ein Antwort-Alias wird erst verbraucht, wenn seine Nachricht zugestellt wird, nach jedem Warten auf einen beschäftigten Besitzer. {tag, Tag} von monitor/3 ersetzt 'DOWN' in der Monitor-Nachricht; Port-Monitore nehmen keine Optionen.

Knoten

Ein Clause-Programm ist ein einzelner, nicht verteilter Knoten, nonode@nohost, und antwortet wie ein solcher OTP-Knoten (builtins/erlang/node.cpp): nodes/0 ist [], nodes(this | known) [nonode@nohost], andere Typen []; nodes/2 liefert {nonode@nohost, #{connection_id => undefined, node_type => this}} für die abgefragten Schlüssel. is_alive/0 ist false, monitor_node/2,3 lösen error:notalive aus, und disconnect_node/1 gibt ignored zurück.

Exit-Signale

Jedes Exit-Signal kommt von einem laufenden Prozess (exit/2, exit_signal/2, link/1) oder vom Ende eines Prozesses. Der Executor verarbeitet es sofort, wenn sein Ziel nicht auf einem anderen Worker läuft, sonst sobald die Zeitscheibe des Ziels geendet hat (Worker, scheduler/signals): Ein beendetes Ziel verlässt die Run-Queue oder sein Warten und wird abgeschlossen (seine Links signalisiert, sein Fehlerbericht geschrieben, sein Kontext freigegeben), bevor das sendende Builtin zurückkehrt. Eine lange verlinkte Kette endet Prozess für Prozess ohne Rekursion.

Signal an einem ProzessFängt Exits nicht abFängt Exits ab
exit(Pid, kill), exit_signal(Pid, kill)Endet mit Grund killedEndet mit Grund killed
Grund normal (von einem Link oder an einen anderen Prozess gesendet)NichtsNachricht {'EXIT', From, normal}
exit(self(), normal)Endet mit Grund normal (Eigenheit von OTP)Nachricht {'EXIT', Self, normal}
exit_signal(self(), normal)NichtsNachricht {'EXIT', Self, normal}
Jeder andere Grund, einschließlich kill von einem LinkEndet mit diesem GrundNachricht {'EXIT', From, Reason}

Ports

Ports sind in Ports spezifiziert: Ein Port ist mit seinem Öffner verlinkt, nimmt wie ein Prozess an Links, Monitoren, Exit-Signalen und registrierten Namen teil und spricht mit seinem verbundenen Prozess über Nachrichten.

Prozesse anhalten

erlang:suspend_process/1,2 und erlang:resume_process/1 (scheduler/suspension.cpp): Jedes Anhalten hält das Ziel einmal im Executor fest, sodass ein angehaltener Prozess erst wieder läuft, wenn jedes Anhalten jedes anhaltenden Prozesses aufgehoben wurde; Nachrichten und Signale erreichen ihn weiterhin (ein Exit-Signal beendet ihn weiterhin), und process_info(Pid, status) meldet suspended. Das Ende eines anhaltenden Prozesses hebt dessen Anhalten auf. Ein synchrones Anhalten eines Prozesses, der auf einem anderen Worker läuft, wartet auf das Ende seiner Zeitscheibe; asynchronous kehrt sofort zurück, {asynchronous, Tag} sendet dem Aufrufer zusätzlich {Tag, suspended}, und unless_suspending antwortet false, wenn der Aufrufer den Prozess bereits anhält. Das Anhalten oder Fortsetzen des Aufrufers selbst, eines beendeten Prozesses, einer Nicht-Pid oder ungültige Optionen sind badarg, ebenso das Fortsetzen eines Prozesses, den der Aufrufer nicht anhält.

Builtins

BuiltinVerhalten
spawn(Fun)badarg, außer Fun ist eine Fun; sonst ruft ein neuer Prozess Fun() auf und löst in diesem Prozess bei anderer Stelligkeit {badarity, {Fun, []}} aus
spawn(M, F, Args)badarg, außer M und F sind Atome und Args eine echte Liste; sonst ruft ein neuer Prozess M:F(Args...) auf und löst in diesem Prozess undef aus, wenn kein Modul sie exportiert und kein Builtin diesen Namen hat
spawn_link(Fun), spawn_link(M, F, Args)Wie spawn, und der neue Prozess wird mit dem Aufrufer verlinkt (Links)
is_process_alive(Pid)badarg, außer Pid ist eine Pid; wahr, solange ihr Prozess nicht geendet hat
spawn_monitor(Fun), spawn_monitor(M, F, Args)Wie spawn, gibt {Pid, Ref} eines neuen Monitors zurück
link(Pid), unlink(Pid)badarg, außer Pid ist eine Pid (Links)
monitor(process, Item)badarg für einen anderen Typ oder ein anderes Element; eine Referenz (Monitore); Item ist eine Pid oder ein registrierter Name
register(Name, Pid), unregister(Name), whereis(Name), registered()Siehe registrierte Namen; Name muss ein Atom sein
demonitor(Ref), demonitor(Ref, Options)badarg, außer Ref ist eine Referenz und Options eine echte Liste aus flush und info
exit(Dest, Reason), exit_signal(Dest, Reason)badarg, außer Dest ist eine Pid oder Referenz; true nach dem Exit-Signal
process_flag(trap_exit, Bool), process_flag(min_heap_size, N), process_flag(save_calls, N)Die vorherige Einstellung; badarg für ein anderes Flag, einen Nicht-Boolean oder eine negative oder nicht ganzzahlige Größe
erlang:send(Dest, Msg), Dest ! MsgMsg, nach dem Senden (Nachrichten); send/2 wird nicht automatisch importiert
spawn(Node, ...), spawn_link(Node, ...), spawn_monitor(Node, ...) (/2, /4)Dieser Knoten (nonode@nohost): wie ohne Node. Anderer Knoten: die nutzlose Pid eines nicht lebenden Knotens von OTP, ein Prozess, der sofort mit Grund noconnection endet, sodass ein Link oder Monitor noconnection meldet; badarg, wenn der Knoten kein Atom ist
erlang:send(Dest, Msg, Options)ok oder noconnect für eine Nachricht an einen anderen Knoten mit der Option noconnect; Optionen nosuspend, noconnect, priority (eine gewöhnliche Nachricht)
send_nosuspend(Dest, Msg), send_nosuspend(Dest, Msg, [noconnect])true; false für einen anderen Knoten mit noconnect
link(Pid, Options), exit(Dest, Reason, Options), exit_signal(Dest, Reason, Options)Wie ohne Optionen; Options ist [] oder [priority] (ein gewöhnliches Signal)
process_flag(Pid, save_calls, N)Die vorherige Einstellung eines anderen Prozesses (0..10000); wird gespeichert, aber Clause zeichnet keine Aufrufe auf; andere Flags badarg
processes_iterator(), processes_next(Iter)Durchlaufen der lebenden Prozesse: {Pid, Iter1} oder none; ein während des Durchlaufs gestarteter Prozess kann erscheinen
bump_reductions(N)true für eine nicht negative Ganzzahl; Clause zählt keine Reduktionen
erlang:suspend_process(Pid), erlang:suspend_process(Pid, Options), erlang:resume_process(Pid)Siehe Prozesse anhalten
erlang:process_display(Pid, backtrace)true nach dem Schreiben des Aufrufstacks des lebenden Prozesses Pid auf die Standardfehlerausgabe, ein Module:Function/Arity pro Zeile, die aktuelle Funktion zuerst; badarg für einen anderen Typ oder einen beendeten Prozess

Der neue Prozess wird am Ende der Warteschlange des Workers seines Elternprozesses eingereiht (Worker); spawn gibt seine Pid sofort zurück.