stdin, stdout, stderr son algunos enteros que se indexan en una estructura de datos que 'sabe' qué canales de E / S se utilizarán para el proceso. Entiendo que esta estructura de datos es única para cada proceso. ¿Los canales de E / S no son más que algunas estructuras de matriz de datos con asignación dinámica de memoria?
8
Respuestas:
En Unix-como sistemas operativos, los flujos de entrada, salida y error estándar se identifican con los descriptores de archivo
0
,1
,2
. En Linux, estos son visibles bajo elproc
sistema de archivos en/proc/[pid]/fs/{0,1,2}
. Estos archivos son en realidad enlaces simbólicos a un dispositivo pseudoterminal en el/dev/pts
directorio.Un pseudoterminal (PTY) es un par de dispositivos virtuales, un pseudoterminal master (PTM) y un pseudoterminal slave (PTS) (colectivamente denominado un par pseudoterminal ), que proporcionan un canal IPC, algo así como un tubo bidireccional entre un programa que espera para conectarse a un dispositivo terminal y a un programa de controlador que utiliza el pseudoterminal para enviar información y recibir información del programa anterior.
Un punto clave es que el esclavo pseudoterminal aparece como un terminal normal, por ejemplo, se puede alternar entre el modo no canónico y el canónico (el valor predeterminado), en el que interpreta ciertos caracteres de entrada, como generar una
SIGINT
señal cuando un carácter de interrupción (normalmente generado presionando Ctrl+ Cen el teclado) se escribe en el maestro pseudoterminal o provoca que el siguienteread()
regrese0
cuando se encuentra un carácter de fin de archivo (normalmente generado por Ctrl+ D). Otras operaciones compatibles con los terminales están activando o desactivando los ecos, configurando el grupo de procesos en primer plano, etc.Los pseudoterminales tienen varios usos:
Permiten programas como
ssh
operar programas orientados a terminal en otro host conectado a través de una red. Un programa orientado a terminal puede ser cualquier programa, que normalmente se ejecutaría en una sesión de terminal interactiva. La entrada, salida y error estándar de un programa de este tipo no se pueden conectar directamente a un zócalo, ya que los zócalos no son compatibles con la funcionalidad relacionada con el terminal mencionada anteriormente.Permiten programas como
expect
manejar un programa interactivo orientado a terminal desde un script.Los utilizan los emuladores de terminal, como
xterm
para proporcionar funcionalidad relacionada con el terminal.Son utilizados por programas como
screen
para multiplexar una sola terminal física entre múltiples procesos.Son utilizados por programas como
script
para registrar todas las entradas y salidas que ocurren durante una sesión de shell.Los PTY de estilo Unix98 , utilizados en Linux, se configuran de la siguiente manera:
El programa controlador abre el multiplexor maestro pseudo-terminal
dev/ptmx
en el cual recibe un descriptor de archivo para un PTM, y se crea un dispositivo PTS en el/dev/pts
directorio. Cada descriptor de archivo obtenido al abrir/dev/ptmx
es un PTM independiente con su propio PTS asociado.El controlador programa las llamadas
fork()
para crear un proceso secundario, que a su vez realiza los siguientes pasos:El niño llama
setsid()
para comenzar una nueva sesión, de la cual el niño es el líder de la sesión. Esto también hace que el niño pierda su terminal de control .El niño procede a abrir el dispositivo PTS que corresponde al PTM creado por el programa del controlador. Como el niño es un líder de sesión, pero no tiene un terminal de control, el PTS se convierte en el terminal de control del niño.
El niño utiliza
dup()
para duplicar el descriptor de archivo para el dispositivo esclavo en su entrada, salida y error estándar.Por último, el niño llama
exec()
para iniciar el programa orientado a terminal que se va a conectar al dispositivo pseudoterminal.En este punto, cualquier cosa que el programa del controlador escriba en el PTM, aparece como entrada al programa orientado a la terminal en el PTS, y viceversa.
Cuando se opera en modo canónico, la entrada al PTS se almacena línea por línea. En otras palabras, al igual que con los terminales regulares, la lectura del programa de un PTS recibe una línea de entrada solo cuando se escribe un carácter de nueva línea en el PTM. Cuando se agota la capacidad de almacenamiento en búfer, se
write()
bloquean más llamadas hasta que se haya consumido parte de la entrada.En el núcleo de Linux, los archivos relacionados con las llamadas al sistema
open()
,read()
,write()
stat()
etc se implementan en la capa virtual del sistema de archivos (VFS), que proporciona una interfaz de sistema de archivos uniforme para los programas de espacio de usuario. El VFS permite que diferentes implementaciones de sistemas de archivos coexistan dentro del núcleo. Cuando los programas de espacio de usuario llaman a las llamadas del sistema antes mencionadas, el VFS redirige la llamada a la implementación apropiada del sistema de archivos.Los dispositivos PTS bajo
/dev/pts
son administrados por ladevpts
implementación del sistema de archivos definida en/fs/devpts/inode.c
, mientras que el controlador TTY que proporciona elptmx
dispositivo de estilo Unix98 se define endrivers/tty/pty.c
.El almacenamiento en búfer entre dispositivos TTY y disciplinas de línea TTY , como pseudoterminales, proporciona una estructura de búfer mantenida para cada dispositivo tty, definida en
include/linux/tty.h
Antes de la versión 3.7 del kernel, el búfer era un búfer invertido :
La estructura contenía almacenamiento dividido en dos tampones de igual tamaño. Los tampones estaban numerados
0
(primera mitad dechar_buf/flag_buf
) y1
(segunda mitad). El controlador almacenó datos en el búfer identificado porbuf_num
. El otro amortiguador podría ser vaciado a la disciplina de línea.El búfer se 'volcó' al alternar
buf_num
entre0
y1
. Cuando sebuf_num
modificóchar_buf_ptr
yflag_buf_ptr
se estableció en el comienzo del búfer identificado porbuf_num
ycount
se estableció en0
.Desde la versión 3.7 del núcleo, los buffers de volteo TTY se han reemplazado por objetos asignados a través de
kmalloc()
organizados en anillos . En una situación normal para un puerto serie controlado por IRQ a velocidades típicas, su comportamiento es prácticamente el mismo que con el antiguo búfer de volteo; dos buffers terminan asignados y el kernel cambia entre ellos como antes. Sin embargo, cuando hay retrasos o aumenta la velocidad, la nueva implementación del búfer funciona mejor ya que el grupo de búferes puede crecer un poco.fuente
De las páginas del manual para cualquiera de las tres explica la respuesta:
fuente
stdin
,stdout
ystderr
desde el punto de vista de la biblioteca C, pero la pregunta es explícitamente sobre la implementación del núcleo. Traté de explicar el punto de vista del núcleo en mi respuesta .