Pregunta

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

cat file.txt | tail -20

¿Este comando imprime todo el contenido del archivo.txt en un búfer, que luego se lee por cola?¿O este comando, por ejemplo, imprime el contenido de file.txt línea por línea y luego hace una pausa en cada línea para que tail lo procese y luego solicita más datos?

La razón por la que pregunto es que estoy escribiendo un programa en un dispositivo integrado 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 Linux (bash) maneja esto, así que deme 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 de Wikipedia relevante, esto no me llevó directamente al artículo pero me ayudó a encontrar esto: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation que tenía la información que estaba buscando.


Lamento no haber sido claro.Por supuesto, estás usando una tubería y, por supuesto, estás usando stdin y stdout de las partes respectivas del comando.Había asumido que eso era demasiado obvio para decirlo.

Lo que pregunto es cómo se maneja/implementa esto.Dado que ambos programas no pueden ejecutarse a la vez, ¿cómo se envían los datos desde stdin a stdout?¿Qué sucede si el primer programa genera datos significativamente más rápido que el segundo programa?¿El sistema simplemente ejecuta el primer comando hasta que termina o su búfer de salida 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? ?

¿Fue útil?

Solución

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

La "magia" aquí está en el sistema operativo.Ambos programas se inician aproximadamente al mismo tiempo y se ejecutan al mismo tiempo (el sistema operativo les asigna períodos de tiempo en el procesador para ejecutarse) como cualquier otro proceso que se ejecuta simultáneamente en su computadora (incluida la aplicación de terminal y el kernel). .Entonces, antes de que se pasen datos, los procesos realizan la inicialización necesaria.En su ejemplo, tail analiza el argumento '-20' y cat analiza el argumento 'file.txt' y abre el archivo.En algún momento, tail llegará al punto donde necesita información y le dirá al sistema operativo que está esperando información.En algún otro momento (ya sea antes o después, no importa), cat comenzará a pasar datos al sistema operativo usando stdout.Esto va a un búfer en el sistema operativo.La próxima vez que tail obtenga un intervalo de tiempo en el procesador después de que cat haya colocado algunos datos en el búfer, recuperará una cantidad de esos datos (o todos) que dejarán el búfer en el sistema operativo.Cuando el búfer está vacío, en algún momento tail tendrá que esperar a que cat genere más datos.Si cat genera datos mucho más rápido de lo que los maneja tail, el búfer se expandirá.eventualmente, cat terminará de generar datos, pero tail seguirá procesando, por lo que cat se cerrará y tail procesará todos los datos restantes en el búfer.El sistema operativo indicará la cola cuando ya no haya datos entrantes con un EOF.Tail procesará los datos restantes.En este caso, es probable que tail solo esté recibiendo todos los datos en un buffer circular de 20 líneas, y cuando el sistema operativo le indica que no hay más datos entrantes, luego vuelca las últimas veinte líneas en su propia salida estándar, que simplemente se muestra en la terminal.Dado que tail es un programa mucho más simple que cat, probablemente pasará la mayor parte del tiempo esperando a que cat coloque datos en el búfer.

En un sistema con múltiples procesadores, los dos programas no solo compartirán intervalos 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 un poco más de detalle, si abre algún tipo de monitor de procesos (específico del sistema operativo) como 'top' en Linux, verá una lista completa de procesos en ejecución, la mayoría de los cuales utilizan efectivamente el 0% del 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 porque permite que otros procesos tengan acceso ilimitado al procesador según 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 kernel que espere n milisegundos antes de darle otro intervalo de tiempo para trabajar.Lo más común es que un programa necesite esperar algo de otro programa, como 'cola' esperando que entren más datos al 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 medio de la ejecución, dando algunos intervalos de tiempo del procesador a otros procesos.'cat' y 'tail' 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 tardan los cabezales de lectura en la unidad de disco en buscar la posición en el disco duro donde está 'archivo.txt'.Si ejecuta el comando por segunda vez, el sistema operativo probablemente tendrá el contenido del archivo.txt almacenado en caché en la memoria y probablemente no verá ningún retraso perceptible (a menos que el archivo.txt sea muy grande o el archivo ya no esté en caché). .)

La mayoría de las operaciones que realiza en su computadora están vinculadas a IO, es decir, generalmente está esperando que los datos provengan de su disco duro o de un dispositivo de red, etc.

Otros consejos

Shog9 ya hizo referencia al artículo de Wikipedia, pero el sección de implementación tiene los detalles que deseas.La implementación básica es un búfer acotado.

cat simplemente imprimirá los datos en la salida estándar, que resulta 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 pausas, tail simplemente lee desde el estándar hacia adentro y cat simplemente escribe hacia el estándar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top