Auf Dateideskriptorebene stdin ist als Dateideskriptor 0 definiert , stdout ist als Dateideskriptor 1 definiert; und stderr ist als Dateideskriptor 2 definiert . Sehen Sie sich das an.
Selbst wenn Ihr Programm oder die Shell den Dateideskriptor 0 ändert (z. B. mit dup2(2) umleitet), bleibt er immer stdin (da per Definition STDIN_FILENO
ist 0).
Systemaufrufe wie open(2) oder pipe(2) oder socket(2) können z.B. STDIN_FILENO
(d. h. 0), wenn dieser Dateideskriptor frei ist (z. B. weil er zuvor close(2)-d war). Aber wenn das passiert, ist es immer noch stdin per Definition.
Natürlich ist in stdio(3) die FILE
stream stdin ist etwas komplexer. Ihr Programm könnte fclose(3), freopen(3), fdopen(3) ...
Es gab zwar schon ein paar Antworten, aber ich fand sie nicht informativ genug, um die ganze Geschichte zu erklären.
Da ich weitergegangen bin und mehr recherchiert habe, füge ich meine Ergebnisse hinzu.
Immer wenn ein Prozess startet, wird ein Eintrag des laufenden Prozesses zu /proc/<pid>
hinzugefügt Verzeichnis. Hier werden alle mit dem Vorgang verbundenen Daten gespeichert. Außerdem weist der Kernel beim Prozessstart dem Prozess 3 Dateideskriptoren für die Kommunikation mit den 3 Datenströmen zu, die als stdin
bezeichnet werden , stdout
und stderr
.
Der Linux-Kernel verwendet einen Algorithmus, um immer eine FD mit dem kleinstmöglichen ganzzahligen Wert zu erstellen, sodass diese Datenströme den Zahlen 0
zugeordnet werden , 1
und 2
.
Da dies nichts anderes als Verweise auf einen Stream sind und wir einen Stream schließen können. Man kann einfach close(<fd>)
anrufen , in unserem Fall close(1)
, um den Dateideskriptor zu schließen.
beim Ausführen von ls -l /proc/<pid>/fd/
, sehen wir dort nur 2 FDs aufgelistet 0
und 2
.
Wenn wir jetzt einen open()
machen Aufruf des Kernels erstellt ein neues FD, um diese neue Dateireferenz abzubilden, und da der Kernel den Algorithmus mit der niedrigsten Ganzzahl zuerst verwendet, wird er den ganzzahligen Wert 1
aufnehmen .
Jetzt zeigt der neu erstellte FD auf die Datei, die wir geöffnet haben (unter Verwendung des open()
Systemaufruf)
Jegliche Datenübertragung, die jetzt stattfindet, erfolgt nicht über den zuvor verknüpften Standarddatenstrom, sondern über die neue Datei, die wir geöffnet haben.
Also ja, wir können den FD 0
abbilden , 1
oder 2
zu einer der Dateien und nicht notwendig stdin
, stdout
oder stderr