Verfügt die Shell über dieselben Standardeingaben, Standardausgaben und Standardfehler wie jeder andere Befehl?

Verfügt die Shell über dieselben Standardeingaben, Standardausgaben und Standardfehler wie jeder andere Befehl?

Die Bash befindet sich beispielsweise unter /bin/bash, das heißt, sie ist ein Befehl und jeder Befehl hat die drei (0,1,2) Poren: Standardeingabe, Standardausgabe, Standardfehler.

Gilt dies auch für die Shell zu 100 Prozent oder gibt es hier Unterschiede hinsichtlich der speziellen Bedeutung der Shell als Befehl bzw. Prozess?

Antwort1

Es ist dasselbe wie bei jedem anderen Programm. Damit können Sie die E/A wie bei anderen Programmen umleiten und weiterleiten.

echo "cat filename" | bash

führt den cat filenameBefehl aus, wenn basher seine Standardeingabe aus der Pipe liest.

bash -c "echo foo" > filename

führt den echo fooBefehl aus und die Ausgabe wird in die Datei umgeleitet.

Unter Unix ist die Shell nichts „Besonderes“. Sie ist nur ein normales Programm, dessen Hauptzweck die Ausführung anderer Programme ist.

Antwort2

Lassen Sie uns einige Begriffe differenzieren:

ABefehlist das, was Sie in Ihre Shell eingeben. Es kann einaliasoder einShell-Funktionoder es kann sich um eineausführbare Datei.

Einausführbare Dateivielleicht einausführbare Binärdatei(also eine, die direkt Maschinencode enthält) oder eineSkript. Zu den Skripten zählen Bash-Skripte, SH-Skripte, Perl-Skripte, Awk-Skripte, Sed-Skripte, Python-Skripte usw.

Die ersten beiden Bytes Ihres Skripts (wenn es direkt als ausführbare Datei ausgeführt werden soll) müssen sein #!, das ist die "magische Zahl", die Ihrem Kernel signalisiert, weitere Bytes zu lesen, bis eine neue Zeile gelesen wird, diese Bytes als Pfad zu einemausführbare Binärdatei, möglicherweise mit einem einzelnen Argument, getrennt durch Leerzeichen (z. B. #!/bin/awk -f), und führen Sie es ausDasBinär ausführbare Datei, wobei der Pfad zum Skript selbst als Argument übergeben wird.

Letztendlich ist das einzige, was der Kernel wirklich ausführen kann, Maschinencode, also eine binäre ausführbare Datei. Binäre ausführbare Dateien wie sh, bash, perl, python, awk usw. werden genanntDolmetscher. Sie interpretieren ein Skript und führen dessen Anweisungen aus. Um ausgeführt werden zu können, müssen sie jedoch selbst im Maschinencode vorhanden sein.

Wenn ein Programm (binäre ausführbare Datei) tatsächlich vom Kernel ausgeführt wird, existiert es alsVerfahren. Eine binäre ausführbare Datei ist einfach eine Datei mit Anweisungen.Verfahrenist eine „laufende Instanz eines Programms“; genauer gesagt handelt es sich um eine im Kernel eingebaute Abstraktion, die über zugehörigen Speicher, Umgebungsvariablen, eine Prozess-ID (PID) verfügt,Dateideskriptorendie es für Eingabe und Ausgabe und andere Attribute verwenden kann. Sie können eine ausführbare Datei mehr als einmal „gleichzeitig“ ausführen (nicht buchstäblich gleichzeitig auf einer Single-Core-Maschine, aber aufgrund der Art und Weise, wie der Kernel CPU-Zyklen zuweist, wird ererscheinengleichzeitig) und jede laufende Instanz wird ein anderer Prozess sein, obwohl es sich bei allen um Instanzen desselben Programms handelt.

0, 1 und 2 – Standardeingabe, Standardausgabe und Standardfehler – sindDateideskriptoren. Ehrlich gesagt existieren sie nur aufgrund einer Konvention. Sie können mit C ein Programm erstellen, das andere Programme startet (ausführt) (verschiedene binäre ausführbare Dateien ausführt), ohne ihnen diese Dateideskriptoren überhaupt zu geben. Jedoch,Da alle Standardprogramme unter der Annahme geschrieben werden, dass die Datei-Deskriptoren 0, 1 und 2 vorhanden sind, werden Sie wahrscheinlich (in den meisten Fällen) nur Fehlermeldungen erhalten und die Programme werden nicht richtig funktionieren.

Um dies wirklich vollständig zu verstehen, sollten Sie verstehenwie ein Prozess zustande kommt. Das ist ein bisschen wie das Wunder der Geburt. ;) Alle Prozesse müssen gestartet werden vonein andererProzess. Ohne sich Gedanken darüber zu machen, wie der erste Prozess beim Hochfahren des Systems gestartet wird, wird der Prozess mit PID 1 „init“ genannt und startet die anderen grundlegenden Prozesse, die Ihr Betriebssystem zum Funktionieren benötigt.

Das Starten eines anderen Prozesses durch einen Prozess erfolgt in zwei grundlegenden Schritten:GabelUndAusführung. Beides sind Systemaufrufe, d.h. es sind Aktionen/Anfragen, die der Prozess sendetzum Kerneldie eigentlich nur der Kernel erfüllen kann.

„Fork“ bedeutet (kurz gesagt): „Kernel, bitte mach eine Kopie von mir.“ („Ich“ ist ein laufender Prozess.) Der Kernel macht eine vollständige Kopie des Prozesses – seine Dateideskriptoren, seinen Speicher, seinen Ausführungsstatus (wo er sich gerade befindet, wenn er die Anweisungen befolgt, die das Programm bilden, dessen Instanz er ist), seine Umgebungsvariablen und so weiter. Es handelt sich also um einen „Klon“ des Prozesses. Wie kann man nun das Original von der Kopie unterscheiden? Nur an einer Sache: dem Rückgabestatus des forkSystemaufrufs. Der Kindprozess erhält „0“ (Erfolg) und der Elternprozess erhält die PID des neu erstellten Kindprozesses. Durch die Überprüfung dieses Rückgabestatus kann jeder Prozess also herausfinden, was er jetzt tun soll (denn denken Sie daran, sie befolgen denselben Satz von Anweisungen!).

"Exec" ist eigentlich "execve()". Kurz gesagt, es fragt den Kernel: "Kernel, bitteersetzenmich (ich bin ein Prozess) mit einer Instanz des in der Datei ______ angegebenen Programms." Und der Programmierer gibt auch dieArgumentedass der neue Prozess haben wird, und dieUmfeld(Array von Umgebungsvariablen), die es haben wird.

Wenn Sie also einen Befehl in die Shell eingeben, passiert in Wirklichkeit (meistens, abgesehen von Sonderfällen wie in die Shell integrierten Befehlen wie cd), dass Ihre Shell (die ein laufender Prozess ist)Gabeln,und dannFührungskräfteder von Ihnen angegebene Befehl.

Wenn Sie eine Ausgabe- oder Eingabeumleitung wie durchgeführt haben /bin/echo hello > /dev/null, dann der gegabelte Kindprozessvor execdem Echopasst seine Datei-Deskriptoren entsprechend an, sodass Datei-Deskriptor 1 (in diesem Beispiel) /dev/nullstatt an Ihr Terminal oder wo auch immer er vorher war, gebunden wird.

Also ja, jede laufende Instanz der ausführbaren Datei /bin/basherwartet einen Dateideskriptor 0, aus dem sie Eingaben lesen kann, einen Dateideskriptor 1, in den sie Ausgaben schreiben kann, und einen Dateideskriptor 2, in den sie Fehlermeldungen und ähnliche Ein-/Ausgaben lesen und schreiben kann.

verwandte Informationen