En el nivel del descriptor de archivo, stdin se define como descriptor de archivo 0 , salida estándar se define como descriptor de archivo 1; y stderr se define como descriptor de archivo 2 . Mira esto.
Incluso si su programa, o el shell, cambia (por ejemplo, redirigir con dup2 (2)) cuál es el descriptor de archivo 0, siempre permanece stdin (ya que por definición STDIN_FILENO
es 0).
Syscalls como open(2) o pipe(2) o socket(2) pueden dar, p. STDIN_FILENO
(es decir, 0) si ese descriptor de archivo está libre (por ejemplo, porque ha sido close(2)-d antes). Pero cuando eso ocurre, sigue siendo stdin por definición.
Por supuesto, en stdio(3), el FILE
stream stdin es un poco más complejo. Su programa podría fclose(3), freopen(3), fdopen(3) ...
Aunque ya existían un par de respuestas, pero no las encontré lo suficientemente informativas como para explicar la historia completa.
Dado que seguí adelante e investigué más, estoy agregando mis hallazgos.
Cada vez que se inicia un proceso, se agrega una entrada del proceso en ejecución al /proc/<pid>
directorio. Este es el lugar donde se guardan todos los datos relacionados con el proceso. Además, al iniciar el proceso, el kernel asigna 3 descriptores de archivo al proceso para la comunicación con los 3 flujos de datos denominados stdin
, stdout
y stderr
.
el kernel de Linux usa un algoritmo para crear siempre un FD con el valor entero más bajo posible, por lo que estos flujos de datos se asignan a los números 0
, 1
y 2
.
Dado que estas no son más que referencias a una transmisión, podemos cerrar una transmisión. Uno puede llamar fácilmente al close(<fd>)
, en nuestro caso close(1)
, para cerrar el descriptor de archivo.
al hacer ls -l /proc/<pid>/fd/
, solo vemos 2 FD enumerados allí 0
y 2
.
Si ahora hacemos un open()
llamar al kernel creará un nuevo FD para mapear esta nueva referencia de archivo y dado que el kernel usa el primer algoritmo de entero más bajo, tomará el valor entero 1
.
Así que ahora, el nuevo FD creado apunta al archivo que abrimos (usando el open()
llamada al sistema)
Cualquiera de las transferencias de datos que ocurren ahora no se realiza a través del flujo de datos predeterminado que se vinculó anteriormente, sino del nuevo archivo que abrimos.
Entonces sí, podemos mapear el FD 0
, 1
o 2
a cualquiera de los archivos y no es necesario stdin
, stdout
o stderr