Nunca he pensado realmente cómo el shell realmente ejecuta comandos canalizados. Siempre me han dicho que el "stdout de un programa se canaliza al stdin de otro", como una forma de pensar en las tuberías. Entonces, naturalmente, pensé que en el caso de decir, A | B, A correría primero, luego B obtiene el stdout de A y usa el stdout de A como su entrada.
Pero he notado que cuando las personas buscan un proceso en particular en ps, incluyen grep -v "grep" al final del comando para asegurarse de que grep no aparezca en el resultado final. Esto significa que en el comando ps aux | grep "bash" | grep -v "grep", lo que significa que ps sabía que grep se estaba ejecutando y, por lo tanto, está en la salida de ps. Pero si ps termina de ejecutarse antes de que su salida se canalice a grep, ¿cómo sabía que grep se estaba ejecutando?
flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY TIME CMD
3773 pts/0 00:00:00 bash
3784 pts/0 00:00:00 ps
3785 pts/0 00:00:00 grep
Respuestas:
Los comandos canalizados se ejecutan simultáneamente. Cuando corres
ps | grep …
, es la suerte del sorteo (o una cuestión de detalles del funcionamiento del shell combinado con el ajuste del programador en las entrañas del núcleo) si se iniciaps
o nogrep
, y en cualquier caso continúan. ejecutar simultáneamenteEsto se usa muy comúnmente para permitir que el segundo programa procese datos a medida que salen del primer programa, antes de que el primer programa haya completado su operación. Por ejemplo
comienza a mostrar las líneas coincidentes en mayúsculas incluso antes de
grep
terminar de recorrer el archivo grande.muestra la primera línea coincidente y puede detener el procesamiento mucho antes de que
grep
haya terminado de leer su archivo de entrada.Si leyó en alguna parte que los programas canalizados se ejecutan en secuencia, huya de este documento. Los programas canalizados se ejecutan simultáneamente y siempre lo han hecho.
fuente
grep
programa, y hay un búfer administrado por el núcleo en la tubería. Para el último, vea ¿Qué tan grande es el buffer de la tubería?El orden en que se ejecutan los comandos en realidad no importa y no está garantizado. Dejando de lado los detalles arcanos de
pipe()
,fork()
,dup()
yexecve()
, la cáscara primero crea la tubería, el conducto para los datos que fluirá entre los procesos y, a continuación, crea los procesos con los extremos de la tubería conectada a ellos. El primer proceso que se ejecuta puede bloquear la espera de entrada del segundo proceso, o bloquear la espera de que el segundo proceso comience a leer datos de la tubería. Estas esperas pueden ser arbitrariamente largas y no importan. Independientemente del orden en que se ejecuten los procesos, los datos eventualmente se transfieren y todo funciona.fuente
A riesgo de vencer a un caballo muerto, la idea errónea parece ser que
es equivalente a
Pero, cuando se creó Unix y los niños montaron dinosaurios para ir a la escuela, los discos eran muy pequeños y era común que un comando bastante benigno consumiera todo el espacio libre en un sistema de archivos. Si
B
fuera algo así , el resultado final de la tubería podría ser mucho más pequeño que ese archivo intermedio. Por lo tanto, se desarrolló la tubería, no como una abreviatura para el “ejecutar A primero, y luego ejecutar B con el aporte de A ‘s de salida”modelo, pero como una manera para ejecutar simultáneamente con y eliminar la necesidad de almacenar el archivo intermedio en el discogrep some_very_obscure_string
B
A
fuente
Por lo general, ejecuta esto en bash. El proceso funciona y comienza simultáneamente, pero el shell los ejecuta en paralelo. ¿Como es posible?
el sistema no garantiza qué tan rápido se ejecutará el exec y se inicia el comando especificado. Es independiente del shell, pero del sistema. Esto es porque:
una vez show
grep
y / ops
comando, y ahora ahora. Depende de qué tan rápido el núcleo realmente inicie procesos usando la función de ejecución del sistema.fuente
exec()
se ejecuta, sino cómoexec()
se intercalan las llamadas y la ejecución de los programas en una tubería .