Bash Pipe Handling


29

¿Alguien sabe cómo gestiona bash el envío de datos a través de las tuberías?

cat file.txt | tail -20 

hace esto de impresión de comandos todos los contenidos de archivo.txt en un buffer, el cual es leído por la cola? ¿O este comando, digamos, imprime el contenido de file.txt línea por línea, y luego hace una pausa en cada línea para que la cola lo procese, y luego solicita más información?

La razón por la que pregunto es que estoy escribiendo un programa en un dispositivo incrustado que básicamente realiza una secuencia de operaciones en algún fragmento de datos, donde la salida de una operación se envía como entrada de la siguiente operación. Me gustaría saber cómo maneja esto linux (bash) así que por favor dame una respuesta general, no específicamente qué sucede cuando ejecuto "cat file.txt | tail -20".

¡Gracias de antemano por sus respuestas!

EDITAR: Shog9 señaló un artículo relevante de Wikipedia, esto no me llevó directamente al artículo, pero me ayudó a encontrar esto: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation que sí tenía la información que estaba buscando.


Disculpe por no aclararme. Por supuesto, estás usando un tubo y, por supuesto, estás usando stdin y stdout de las partes respectivas del comando. Había supuesto que era demasiado obvio para decirlo.

Lo que estoy preguntando es cómo se maneja/implementa esto. Dado que ambos programas no se pueden ejecutar a la vez, ¿cómo se envían los datos de stdin a stdout? ¿Qué sucede si el primer programa genera datos significativamente más rápido que el segundo programa? ¿El sistema acaba de ejecutar el primer comando hasta que finaliza o su búfer estándar está lleno y luego pasa al siguiente programa, y ​​así sucesivamente en un bucle hasta que no quedan más datos para procesar o hay un mecanismo más complicado? ?

54

Decidí escribir una explicación un poco más detallada.

La "magia" aquí radica en el sistema operativo. Ambos programas se inician aproximadamente al mismo tiempo y se ejecutan al mismo tiempo (el sistema operativo les asigna porciones de tiempo en el procesador para que se ejecuten) como cualquier otro proceso simultáneo en su computadora (incluyendo la aplicación del terminal y el kernel). . Entonces, antes de que se pasen los datos, los procesos están haciendo la inicialización necesaria. En su ejemplo, tail está analizando el argumento '-20' y cat está analizando el argumento 'file.txt' y está abriendo el archivo. En algún punto, la cola llegará al punto en que necesita información y le indicará al sistema operativo que está esperando la entrada. En algún otro punto (ya sea antes o después, no importa) cat comenzará a pasar datos al sistema operativo usando stdout. Esto va a un buffer en el sistema operativo. La próxima vez que tail obtenga una porción de tiempo en el procesador después de que algunos datos hayan sido colocados en el búfer por cat, recuperará cierta cantidad de esos datos (o todo) que dejan el búfer en el sistema operativo. Cuando el búfer está vacío, en algún punto la cola tendrá que esperar a que cat entregue más datos. Si cat está generando datos mucho más rápido que tail lo está manejando, el buffer se expandirá.eventualmente se terminará el gato enviando datos, pero la cola seguirá procesándose, por lo que cat cerrará y tail procesará todos los datos restantes en el búfer. El sistema operativo señalará la cola cuando no haya más datos entrantes con un EOF. Cola procesará los datos restantes. En este caso, tail probablemente está recibiendo todos los datos en un búfer circular de 20 líneas, y cuando el sistema operativo le indica que no hay más datos entrantes, entonces vuelca las últimas veinte líneas a su propia stdout, que solo se muestra en la terminal. Como tail es un programa mucho más simple que cat, es probable que pase la mayor parte del tiempo esperando que cat coloque datos en el búfer.

En un sistema con múltiples procesadores, los dos programas no solo compartirán cortes de tiempo alternos en el mismo núcleo del procesador, sino que probablemente se ejecutarán al mismo tiempo en núcleos separados.

Para entrar en más detalles, si abre algún tipo de monitor de proceso (específico del sistema operativo) como 'top' en Linux verá una lista completa de procesos en ejecución, la mayoría de los cuales están utilizando efectivamente 0% de el procesador. La mayoría de las aplicaciones, a menos que estén procesando datos, pasan la mayor parte de su tiempo sin hacer nada. Esto es bueno, ya que permite que otros procesos tengan acceso sin restricciones al procesador de acuerdo con sus necesidades. Esto se logra básicamente de tres maneras. Un proceso podría llegar a una instrucción de estilo sleep (n) donde básicamente le dice al núcleo que espere n milisegundos antes de darle otra porción de tiempo para trabajar. Lo más común es que un programa necesite esperar algo de otro programa, como 'cola' esperando que ingresen más datos en el búfer. En este caso, el sistema operativo activará el proceso cuando haya más datos disponibles. Por último, el kernel puede adelantarse a un proceso en el medio de la ejecución, dando algunos cortes de tiempo del procesador a otros procesos. 'gato' y 'cola' son programas simples. En este ejemplo, tail pasa la mayor parte del tiempo esperando más datos en el búfer, y cat pasa la mayor parte del tiempo esperando que el sistema operativo recupere datos del disco duro. El cuello de botella es la velocidad (o lentitud) del medio físico en el que se almacena el archivo. Ese retraso perceptible que puede detectar cuando ejecuta este comando por primera vez es el tiempo que les toma a los cabezales de lectura en la unidad de disco buscar la posición en el disco duro donde está 'file.txt'. Si ejecuta el comando por segunda vez, es probable que el sistema operativo tenga el contenido de file.txt almacenado en la memoria caché, y es probable que no vea ningún retraso perceptible (a menos que file.txt sea muy grande o que el archivo ya no esté en caché). .)

mayoría de las operaciones que realiza en su equipo están obligados IO, lo que quiere decir que usted está en la espera de que los datos provienen de su disco duro, o desde un dispositivo de red, etc.


0

cat simplemente imprimirá los datos a la salida estándar, que pasa a ser redirigido a la entrada estándar de la cola. Esto se puede ver en la página de manual de bash.

En otras palabras, no hay pausa en curso, la cola solo está leyendo desde el estándar y el gato está escribiendo a la salida estándar.


1

Shog9 ya hace referencia al artículo de Wikipedia, pero el implementation section tiene los detalles que desea. La implementación básica es un buffer limitado.