Nach diesem und dies wird ein Sub - Shell mithilfe von Klammern gestartet (…)
.
( echo "Hello" )
Nach dieser , dies und dies ist ein Prozess gegabelt ist , wenn der Befehl mit einem gestartet&
echo "Hello" &
Die Posix-Spezifikation verwendet das Wort subshell
auf dieser Seite , definiert es jedoch nicht und definiert auf derselben Seite auch nicht den "untergeordneten Prozess" .
Beide verwenden die Kernelfunktion fork()
, richtig?
Was ist der genaue Unterschied, wenn man einige Gabeln als "Sub-Shell" und andere Gabeln als "untergeordneten Prozess" bezeichnet?
child process
könnte eine andere Umgebung haben alsmain
: Wie in( LANG=C eval 'echo "$LANG"' )
. Ist dieser untergeordnete Prozess (in Klammern) auch eine Unterschale (andere Umgebung)?( )
ist per Definition eine Subshell mit einer eigenen Ausführungsumgebung. Mein Punkt ist, dass eine Subshell nicht als untergeordneter Prozess implementiert werden muss (wie Stéphane in seiner Antwort mit dem Beispiel ksh93 hervorhebt). Es sieht so aus, als müssten Subshell und Child-Prozess nicht beide Ergebnisse einesfork()
Aufrufs sein. Daher scheint es mir nicht der richtige Standpunkt zu sein, nach dem Unterschied zwischen zwei Arten von Gabel zu suchen. Deshalb habe ich versucht, Ihre Frage besser zu verstehen.Antworten:
In der POSIX-Terminologie ist eine Subshell-Umgebung mit dem Begriff der Shell-Ausführungsumgebung verknüpft .
Eine Subshell-Umgebung ist eine separate Shell-Ausführungsumgebung, die als Duplikat der übergeordneten Umgebung erstellt wird. Diese Ausführungsumgebung enthält Dinge wie geöffnete Dateien, Umask, Arbeitsverzeichnis, Shell-Variablen / Funktionen / Aliase ...
Änderungen an dieser Subshell-Umgebung wirken sich nicht auf die übergeordnete Umgebung aus.
Traditionell in der Bourne-Shell oder ksh88, auf der die POSIX-Spezifikation basiert, wurde dies durch Verzweigen eines untergeordneten Prozesses durchgeführt.
Die Bereiche, in denen POSIX die Ausführung von Befehlen in einer Subshell-Umgebung erfordert oder zulässt, sind diejenigen, in denen ksh88 traditionell einen untergeordneten Shell-Prozess gabelte.
Implementierungen werden jedoch nicht gezwungen, dafür einen untergeordneten Prozess zu verwenden.
Eine Shell kann stattdessen wählen, diese separate Ausführungsumgebung nach Belieben zu implementieren.
Zum Beispiel speichert ksh93 die Attribute der übergeordneten Ausführungsumgebung und stellt sie nach Beendigung der Subshell-Umgebung in Kontexten wieder her, in denen das Forking vermieden werden kann (eine Optimierung, da das Forking auf den meisten Systemen recht teuer ist).
Zum Beispiel in:
POSIX erfordert die
cd /foo
Ausführung in einer separaten Umgebung und die Ausgabe von:Es ist nicht erforderlich, dass es in einem separaten Prozess ausgeführt wird. Wenn zum Beispiel stdout zu einer kaputten Pipe wird, kann beim
pwd
Ausführen in der Subshell-Umgebung das SIGPIPE sehr gut an den einzigen Shell-Prozess gesendet werden.Die meisten Shells einschließlich
bash
implementieren es, indem sie den Code(...)
in einem untergeordneten Prozess auswerten (während der übergeordnete Prozess auf seine Beendigung wartet), aber ksh93 wird stattdessen beim Ausführen des Codes im(...)
selben Prozess alles im selben Prozess ausführen :cd
, speichern Sie das vorherige Arbeitsverzeichnis ( in der Regel auf einem Dateideskriptor mit O_CLOEXEC geöffnet), außer dem Wert der OLDPWD, PWD Variablen und alles , wascd
ändern könnte und dann tut diechdir("/bar")
fchdir()
auf dem gespeicherten fd) und alles andere, was die Subshell möglicherweise geändert hat.Es gibt Kontexte, in denen ein untergeordneter Prozess nicht vermieden werden kann. ksh93 gibt sich nicht ein:
var=$(subshell)
(subshell)
Aber tut in
{ subshell; } &
{ subshell; } | other command
Das heißt, die Fälle, in denen Dinge in separaten Prozessen ausgeführt werden müssen, damit sie gleichzeitig ausgeführt werden können.
ksh93-Optimierungen gehen noch weiter. Zum Beispiel während in
Die meisten Shells würden einen Prozess
pwd
verzweigen, das untergeordnete Element den Befehl ausführen lassen, dessen Standardausgabe in eine Pipe umgeleitet wirdpwd
, das aktuelle Arbeitsverzeichnis in diese Pipe schreiben und der übergeordnete Prozess das Ergebnis am anderen Ende der Pipe lesen undksh93
all das von beiden virtualisieren erfordert die Gabel noch das Rohr. Eine Gabel und ein Rohr würden nur für nicht eingebaute Befehle verwendet.Beachten Sie, dass es andere Kontexte als Unterschalen gibt, für die Schalen einen untergeordneten Prozess verzweigen. Um beispielsweise einen Befehl auszuführen, der in einer separaten ausführbaren Datei gespeichert ist (und der kein Skript für denselben Shell-Interpreter ist), müsste eine Shell einen Prozess verzweigen, um diesen Befehl darin auszuführen, wie dies sonst nicht der Fall wäre Sie können weitere Befehle ausführen, nachdem dieser Befehl zurückgegeben wurde.
Im:
Dies ist keine Subshell. Der Befehl wird in der aktuellen Shell-Ausführungsumgebung ausgewertet. Die
n
Variable der aktuellen Shell-Ausführungsumgebung wird inkrementiert. Die Shell gibt jedoch einen untergeordneten Prozess aus, um diesen/bin/echo
Befehl mit der Erweiterung$((n += 1))
als Argument auszuführen .Viele Shells implementieren eine Optimierung, indem sie einen untergeordneten Prozess nicht dazu veranlassen, diesen externen Befehl auszuführen, wenn es sich um den letzten Befehl eines Skripts oder einer Unterschale handelt (für die Unterschalen, die als untergeordnete Prozesse implementiert sind). (
bash
Dies geschieht jedoch nur, wenn dieser Befehl der einzige Befehl der Subshell ist.)Dies bedeutet, dass bei diesen Shells, wenn der letzte Befehl in der Subshell ein externer Befehl ist, die Subshell keinen zusätzlichen Prozess erzeugt. Wenn Sie vergleichen:
mit
Es wird die gleiche Anzahl von Prozessen erstellt, nur im zweiten Fall wird die zweite Verzweigung früher ausgeführt, so dass die
a=2
Zweig in einer Subshell-Umgebung ausgeführt wird.quelle
Unterschale
Die untergeordnete Shell wird auch als Subshell bezeichnet. Die Subshell kann aus der übergeordneten Shell und aus einer anderen Shell erstellt werden. Die Unterschale kann erstellt werden mit:
1. Prozessliste
Eine Prozessliste ist eine in Klammern eingeschlossene Befehlsgruppierung. Beispiel:
Dadurch werden das aktuelle Arbeitsverzeichnis und die Anzahl der erzeugten Shells gedruckt. HINWEIS Hervorrufen Subshell ist teuer.
2. Coprozess
Es erzeugt eine Unterschale im Hintergrundmodus und führt einen Befehl innerhalb dieser Unterschale aus.
Wenn Sie einen
jobs
Befehl eingebenSie sehen den Schlaf als Hintergrundprozess, der im Hintergrund ausgeführt wird.
Forking eines untergeordneten Prozesses
Ein untergeordneter Prozess beim Rechnen ist ein Prozess, der von einem anderen Prozess erstellt wird. Immer wenn ein externer Befehl ausgeführt wird, wird ein untergeordneter Prozess erstellt. Diese Aktion wird als Gabeln bezeichnet.
Ebenso
ps -f
wie der externe Befehl (dh ein externer Befehl, der manchmal als Dateisystembefehl bezeichnet wird, ist ein Programm, das außerhalb der Bash-Shell vorhanden ist). Dadurch wird ein untergeordneter Prozess mit der übergeordneten ID der Bash-Shell erstellt, von der aus er ausgeführt wird.quelle
Beide (Subshell und untergeordnete Shell) sind ein separater Prozess als die übergeordnete Shell (beide sind untergeordnete Elemente der übergeordneten Shell). Das heißt, sie haben unterschiedliche PIDs. Und beide beginnen mit einer Abzweigung (Kopie) der übergeordneten Shell.
Eine Subshell ist eine Kopie der übergeordneten Shell, in der Variablen, Funktionen, Flags und alles wie in der übergeordneten Shell verfügbar sind. Änderungen solcher Werte wirken sich nicht auf das übergeordnete Element aus.
Eine untergeordnete Shell startet als Fork, wird jedoch auf die durch die Startkonfigurationen angegebenen Shell-Standardwerte zurückgesetzt. Es wird zu einem Prozess, mit dem Code ausgeführt wird (entweder eine Shell oder ein Befehl).
Eine Unterschale kann auf Variablenwerte zugreifen:
Eine untergeordnete Shell konnte nicht (nicht exportierte Variablen):
quelle