Wie funktioniert das integrierte „exec bash“ intern?

Wie funktioniert das integrierte „exec bash“ intern?

AusDasLink: Ich erhalte Folgendes zum integrierten Befehl „exec bash“:

Wenn der Befehl angegeben wird,ersetzt die Schaleohne einen neuen Prozess zu erstellen.

Wie genau ersetzt es die Shell (d. h. wie funktioniert es intern)? Funktioniert der exec*()Systemaufruf genauso?

Antwort1

Ja, das execintegrierte Programm verwendet letztendlich einen der exec*()Systemaufrufe. Dasselbe gilt für das normale Ausführen von Befehlen. Wenn Sie jedoch verwenden exec, wird der Systemaufruf nicht fork()zuerst verwendet, um einen neuen Prozess zu erstellen. Das Ergebnis ist, dass der neue Befehl die Shell ersetzt.

Antwort2

Ich habe dies straceauf einer laufenden bashInstanz durchgeführt. Dann habe ich den Befehl aufgerufen exec sleep 100. Sehen Sie nun, was passiert ist:

access("/bin/sleep", X_OK)              = 0
...
execve("/bin/sleep", ["sleep", "100"], [/* 14 vars */]) = 0
...
nanosleep({100, 0},
...
exit_group(0)                           = ?

Sie sehen also, dass es fast genauso abläuft wie beim sleepnormalen Aufruf. bashÜberprüft, ob die Ausführungsberechtigung ( X_OK) für /bin/sleepden access()Systemaufruf erteilt wurde. execve()Führt dann das Programm aus, auf das der Dateiname verweist. Nach execve()dem Systemaufruf sleephat er die Kontrolle über den Prozess. Er macht folgende Dinge: nanosleep(). Er behält auch die gleiche PID. Nach sleepdem Ende endet auch der Prozess. Egal, sleepob basher nicht mehr läuft.

Beweis:

In einem weiteren Fenster habe ich den Vorgang mit verfolgt ps. Vor dem Ausführen des Befehls sah es so aus:

$ ps -o stat,pid,cmd -p <pid>
Ss+  10905 -bash

Und beim Laufen:

$ ps -o stat,pid,cmd -p <pid>
Ss+  10905 sleep 100

Nach sleepAbschluss des Vorgangs verschwand er.

Was passiert, wenn ich es normal ausführe?

access("/bin/sleep", X_OK)              = 0
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f6c9fd089d0) = 19261
...
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 19261
...
--- SIGCHLD (Child exited) @ 0 (0) ---

Die Ausführungsberechtigung wird geprüft. Dann wird ein Kindprozess erzeugt clone(). Die bashInstanz befindet sich nun in der Hintergrundprozessgruppe, sleepist in der Vordergrundprozessgruppe. Und zum Schluss wait4()wartet der Aufruf, bis der Kindprozess beendet ist (das dauert 100 Sekunden).

verwandte Informationen