He estado leyendo sobre cómo se implementan las canalizaciones en el kernel de Linux y quería validar mi comprensión. Si soy incorrecto, se seleccionará la respuesta con la explicación correcta.
- Linux tiene un VFS llamado pipefs que está montado en el kernel (no en el espacio del usuario)
- pipefs tiene un súper bloque único y está montado en su propia raíz (
pipe:
), junto a/
- pipefs no se puede ver directamente a diferencia de la mayoría de los sistemas de archivos
- La entrada a pipefs es a través de
pipe(2)
syscall - La
pipe(2)
llamada al sistema utilizada por los shells para canalizar con el|
operador (o manualmente desde cualquier otro proceso) crea un nuevo archivo en pipefs que se comporta más o menos como un archivo normal - El archivo en el lado izquierdo del operador de tubería se
stdout
redirige al archivo temporal creado en pipefs - El archivo en el lado derecho del operador de tubería tiene su
stdin
conjunto en el archivo en pipefs - pipefs se almacena en la memoria y, a través de la magia del kernel, no se debe paginar
¿Es esta explicación de cómo funcionan las tuberías (p ls -la | less
. Ej. ) Bastante correcta?
Una cosa que no entiendo es cómo algo como bash establecería un proceso ' stdin
o stdout
al descriptor de archivo devuelto por pipe(2)
. Todavía no he podido encontrar nada al respecto.
pipe()
llamada del kernel junto con la maquinaria que lo soporta (pipefs
, etc.) es de un nivel mucho más bajo que el|
operador ofrecido en su shell. Este último generalmente se implementa utilizando el primero, pero no tiene que ser así.|
operador solo está llamandopipe(2)
como un proceso como lo hace bash.Respuestas:
Su análisis hasta ahora es generalmente correcto. La forma en que un shell puede establecer el stdin de un proceso en un descriptor de tubería podría ser (pseudocódigo):
fuente
dup2
se necesita la llamada y no puede asignar directamente el descriptor de tubería a stdin?pipe()
. Ladup2()
llamada permite a la persona que llama copiar el descriptor de archivo a un valor numérico específico (necesario porque 0, 1, 2 son stdin, stdout, stderr). Ese es el equivalente del núcleo de "asignar directamente a stdin". Tenga en cuenta que la variable global de la biblioteca de tiempo de ejecución Cstdin
es aFILE *
, que no está relacionada con el núcleo (aunque se inicializa para conectarse al descriptor 0).dup2
llamada no cambiap[1]
. En su lugar, hace los dos identificadoresp[1]
y0
apuntan al mismo objeto del núcleo (la tubería). Dado que el proceso secundario no necesita dos identificadores estándar (y dep[1]
todos modos no sabría cuál es el identificador numerado ),p[1]
se cierra antesexec
.