A livello di descrittore di file, stdin è definito come descrittore di file 0 , stdout è definito come descrittore di file 1; e stderr è definito come descrittore di file 2 . Guarda questo.
Anche se il tuo programma, o la shell, cambia (ad es. reindirizzamento con dup2(2)) qual è il descrittore di file 0, rimane sempre stdin (poiché per definizione STDIN_FILENO
è 0).
Chiamate di sistema come open(2) o pipe(2) o socket(2) possono dare ad es. STDIN_FILENO
(cioè 0) se quel descrittore di file è libero (ad esempio perché è stato close(2)-d prima). Ma quando ciò accade, è ancora stdin per definizione.
Naturalmente, in stdio(3), il FILE
stream stdin è un po' più complesso. Il tuo programma potrebbe fclose(3), freopen(3), fdopen(3) ...
Sebbene esistessero già un paio di risposte, non le ho trovate abbastanza informative da spiegare la storia completa.
Dato che sono andato avanti e ho fatto ulteriori ricerche, aggiungo le mie scoperte.
Ogni volta che un processo viene avviato, una voce del processo in esecuzione viene aggiunta a /proc/<pid>
directory. Questo è il luogo in cui vengono conservati tutti i dati relativi al processo. Inoltre, all'avvio del processo, il kernel alloca 3 descrittori di file al processo per la comunicazione con i 3 flussi di dati indicati come stdin
, stdout
e stderr
.
il kernel Linux utilizza un algoritmo per creare sempre un FD con il valore intero più basso possibile in modo che questi flussi di dati siano mappati sui numeri 0
, 1
e 2
.
Poiché questi non sono altro che riferimenti a un flusso e possiamo chiudere un flusso. Si può facilmente chiamare close(<fd>)
, nel nostro caso close(1)
, per chiudere il descrittore di file.
facendo ls -l /proc/<pid>/fd/
, vediamo solo 2 FD elencati lì 0
e 2
.
Se ora eseguiamo un open()
chiamare il kernel creerà un nuovo FD per mappare questo nuovo riferimento al file e poiché il kernel usa l'algoritmo del primo numero intero più basso, prenderà il valore intero 1
.
Quindi ora, il nuovo FD creato punta al file che abbiamo aperto (usando il open()
chiamata di sistema)
Qualsiasi trasferimento di dati che avviene ora non avviene tramite il flusso di dati predefinito precedentemente collegato, ma il nuovo file che abbiamo aperto.
Quindi sì, possiamo mappare l'FD 0
, 1
o 2
a qualsiasi file e non è necessario stdin
, stdout
o stderr