¿Cómo funciona una tubería en Linux?

6 minutos de lectura

¿Cómo funciona la tubería? Si ejecuto un programa a través de CLI y redirijo la salida a un archivo, ¿podré canalizar ese archivo a otro programa mientras se escribe?

Básicamente, cuando se escribe una línea en el archivo, me gustaría que se canalice inmediatamente a mi segunda aplicación (estoy tratando de dibujar dinámicamente un gráfico a partir de un programa existente). Simplemente no estoy seguro si la tubería completa el primer comando antes de pasar al siguiente comando.

¡Cualquier retroalimentación sería muy apreciada!

  • Mencionó una interfaz CLI para el programa 1 a continuación: si el programa 1 depende de la entrada interactiva, es probable que sea un mal candidato para la canalización directa, como muestra la respuesta de Adam.

    –Harper Shelby

    2 de julio de 2009 a las 2:46

  • Las tuberías en Windows son diferentes a las de Linux… Creo que Linux usa algún tipo de búfer en anillo y usa teorías de programación concurrentes (problema productor-consumidor, etc.) para funcionar bien. Creo que Windows espera hasta que se completa el primer programa antes de llamar al segundo.

    – Ape-inago

    2 de julio de 2009 a las 4:08

avatar de usuario
adam rosenfield

Si desea redirigir la salida de un programa a la entrada de otro, simplemente use una canalización simple:

program1 arg arg | program2 arg arg

Si desea guardar la salida de program1 en un archivo y canalizarlo en program2puedes usar tee(1):

program1 arg arg | tee output-file | program2 arg arg

Todos los programas en una canalización se ejecutan simultáneamente. La mayoría de los programas suelen utilizar bloqueando E/S: si cuando intentan leer su entrada y no hay nada allí, cuadra: es decir, se detienen y el sistema operativo los desprograma para que se ejecuten hasta que haya más entradas disponibles (para evitar consumir la CPU). De manera similar, si un programa anterior en la tubería está escribiendo datos más rápido de lo que un programa posterior puede leerlos, eventualmente el búfer de la tubería se llena y el escritor se bloquea: el sistema operativo lo cancela hasta que el lector vacía el búfer de la tubería, y luego puede seguir escribiendo de nuevo.


EDITAR

Si desea utilizar la salida de program1 como parámetros de la línea de comandos, puede utilizar las comillas inversas o el $() sintaxis:

# Runs "program1 arg", and uses the output as the command-line arguments for
# program2
program2 `program1 arg`

# Same as above
program2 $(program1 arg)

los $() se debe preferir la sintaxis, ya que son más claras y se pueden anidar.

  • Por alguna razón, el programa inicial (programa 1 en este caso) no coopera con las tuberías. ¿Se necesita un código especial dentro de él? Traté de hacer una canalización simple como usted había diseñado y 1) la interfaz CLI para el programa 1 no se inició, y 2) el programa 2 solicitó parámetros (aunque estoy tratando de pasar la salida de 1 como los parámetros para 2)

    Jon

    2 de julio de 2009 a las 2:37

  • @Jon, parece que el programa 1 no está enviando su salida a la salida estándar o el programa 2 no está leyendo desde la entrada estándar. ¿Qué programas estás tratando de ejecutar?

    –Matthew Crumley

    2 de julio de 2009 a las 2:54

  • Hay un indicador que algunos programas pueden leer para averiguar si están en una tubería o no… ‘ls’ hace esto para decidir cómo mostrar la información del archivo (cuando está en una tubería, tiene cada archivo en una línea de su propia, etc)

    – Ape-inago

    2 de julio de 2009 a las 4:12

  • @Matt, usé el ejemplo presentado en la página del manual para pipe y echo. Supuse que esto tomaría una entrada y luego la imprimiría dos veces o al menos una vez. No tan. Mi CLI se parece a $./test “testing” | eco. La prueba es básicamente un programa que pone una cadena en una tubería y la extrae carácter por carácter.

    Jon

    2 de julio de 2009 a las 17:45

  • @Jon: echo no lee su stdin, solo mira sus parámetros de línea de comando. ¿Qué estás tratando de hacer exactamente?

    – Adam Rosenfield

    2 de julio de 2009 a las 18:59

Tubería no completa el primer comando antes de ejecutar el segundo. Las tuberías de Unix (y Linux) ejecutan todos los comandos al mismo tiempo. Un comando será suspendido si

  • Está hambriento de entrada.

  • Ha producido una producción significativamente mayor de la que su sucesor está listo para consumir.

Para la mayoría de los programas, la salida es amortiguado, lo que significa que el sistema operativo acumula una cantidad sustancial de salida (quizás unos 8000 caracteres) antes de pasarla a la siguiente etapa de la canalización. Este almacenamiento en búfer se utiliza para evitar demasiados cambios entre procesos y kernel.

Si desea que la salida en una canalización se envíe de inmediato, puede usar sin búfer I/O, que en C significa llamar a algo como fflush() para asegurarse de que cualquier salida almacenada en búfer sea inmediatamente enviado al siguiente proceso. La entrada sin búfer también es posible, pero generalmente es innecesaria porque un proceso que no recibe entrada normalmente no espera a que se llene el búfer, sino que procesará cualquier entrada que pueda obtener.

Para aplicaciones típicas, no se recomienda la salida sin búfer; generalmente obtiene el mejor rendimiento con los valores predeterminados. Sin embargo, en su caso, donde desea hacer gráficos dinámicos inmediatamente, el primer proceso tiene la información disponible, definitivamente desea utilizar una salida sin búfer. Si está usando C, llamando fflush(stdout) siempre que desee la salida enviada será suficiente.

Si sus programas se comunican usando stdin y stdoutluego asegúrese de que está llamando fflush(stdout) después de escribir o encontrar alguna forma de deshabilitar el almacenamiento en búfer de E/S estándar. La mejor referencia que se me ocurre que realmente describe cómo implementar mejor las canalizaciones en C/C++ es Programación Avanzada en el Entorno UNIX o Programación de redes UNIX: Volumen 2. Probablemente podrías empezar con un Este artículo así como.

Si sus dos programas insisten en leer y escribir archivos y no usan stdin/stdout, puede encontrar que puede usar un tubería con nombre en lugar de un archivo.

Cree una tubería con nombre con el comando mknod(1):

$ mknod /tmp/named-pipe p

Luego configure sus programas para leer y escribir en /tmp/named-pipe (use cualquier ruta/nombre que considere apropiado).

En este caso, ambos programas se ejecutarán en paralelo, bloqueándose según sea necesario cuando la tubería se llene/vacíe como se describe en las otras respuestas.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad