¿Cómo entender las tuberías?


21

Cuando acabo de usar pipe en bash, no pensé más en esto. Pero cuando leo un ejemplo de código C usando la llamada al sistema pipe () junto con fork (), me pregunto cómo entender las tuberías, incluidas las tuberías anónimas y las tuberías con nombre.

A menudo se escucha que "todo en Linux / Unix es un archivo". Me pregunto si una tubería es realmente un archivo, de modo que una parte que conecta se escribe en el archivo de la tubería, y la otra parte lee del archivo de la tubería. En caso afirmativo, ¿dónde se crea el archivo de tubería para una tubería anónima? En / tmp, / dev, o ...?

Sin embargo, a partir de ejemplos de tuberías con nombre, también aprendí que usar tuberías tiene una ventaja de rendimiento en espacio y tiempo sobre el uso explícito de archivos temporales, probablemente porque no hay archivos involucrados en la implementación de tuberías. También las tuberías no parecen almacenar datos como lo hacen los archivos. Así que dudo que una tubería sea en realidad un archivo.

Respuestas:


23

Acerca de su pregunta de rendimiento, las canalizaciones son más eficientes que los archivos porque no se necesita disco IO. Por cmd1 | cmd2lo tanto, es más eficiente que cmd1 > tmpfile; cmd2 < tmpfile(esto podría no ser cierto si tmpfileestá respaldado en un disco RAM u otro dispositivo de memoria como tubería con nombre; pero si es una tubería con nombre, cmd1debe ejecutarse en segundo plano ya que su salida puede bloquearse si la tubería se llena ) Si necesita el resultado cmd1y aún necesita enviar su salida cmd2, debe cmd1 | tee tmpfile | cmd2permitir cmd1y cmd2ejecutar en paralelo evitando las operaciones de lectura de disco cmd2.

Las canalizaciones con nombre son útiles si muchos procesos leen / escriben en la misma canalización. También pueden ser útiles cuando un programa no está diseñado para usar stdin / stdout para su IO que necesita usar archivos . Puse los archivos en cursiva porque las canalizaciones con nombre no son exactamente archivos en un punto de vista de almacenamiento, ya que residen en la memoria y tienen un tamaño de búfer fijo, incluso si tienen una entrada del sistema de archivos (para fines de referencia). Otras cosas en UNIX tienen entradas del sistema de archivos sin ser archivos: solo piense en /dev/nullu otras entradas en /devo /proc.

Como las tuberías (con y sin nombre) tienen un tamaño de búfer fijo, las operaciones de lectura / escritura pueden bloquearse, lo que hace que el proceso de lectura / escritura pase al estado IOWait. Además, ¿cuándo recibe un EOF cuando lee desde un búfer de memoria? Las reglas sobre este comportamiento están bien definidas y se pueden encontrar en el hombre.

Una cosa que no puede hacer con las tuberías (con nombre y sin nombre) es buscar de nuevo en los datos. Como se implementan utilizando un búfer de memoria, esto es comprensible.

Sobre "everything in Linux/Unix is a file", no estoy de acuerdo. Las canalizaciones con nombre tienen entradas del sistema de archivos, pero no son exactamente archivos. Las canalizaciones sin nombre no tienen entradas del sistema de archivos (excepto tal vez en /proc). Sin embargo, la mayoría de las operaciones de E / S en UNIX se realizan mediante la función de lectura / escritura que necesita un descriptor de archivo , incluida la tubería (y el socket) sin nombre. No creo que podamos decir eso "everything in Linux/Unix is a file", pero seguramente podemos decir eso "most IO in Linux/Unix is done using a file descriptor".


¡Gracias! ¿Están los dos comandos conectados por una tubería que se ejecuta en paralelo, en lugar de que el segundo comience a ejecutarse después de que finalice el primero?
Tim

Sí, los 2 comandos se ejecutan en paralelo. Si no lo fueran y la primera salida fuera más que el búfer, se bloquearía. Puede probarlo ejecutando cmd1 > fifoy cmd2 < fifoen 2 shells diferentes, creando la tubería con nombre mkfifo fifo.
jfg956

Otra prueba que puede hacer es matar cmd2mientras cmd1aún se está ejecutando: cmd1probablemente dejará de informar un mensaje de tubería roto.
jfg956

¡Gracias! ¿Qué quieres decir con que estaría bloqueado? Si esto sucede, ¿significa que se perderá la fecha en la secuencia después del bloqueo?
Tim

2
Los datos no se pierden. Si el búfer de la tubería está lleno, cmd1la escritura en la tubería solo volverá cuando cmd2haya leído los datos de la tubería. De la misma manera, cmd2la lectura de una tubería se bloqueará si el búfer está vacío hasta que se cmd1escriba en la tubería.
jfg956

4

Dos de los fundamentos básicos de la filosofía UNIX son

  1. Hacer pequeños programas que hagan bien una cosa.
  2. y esperar que la salida de cada programa se convierta en la entrada a otro programa,
    aún desconocido.

    El uso de tuberías le permite aprovechar los efectos de estos dos
    fundamentos de diseño para crear cadenas de comandos extremadamente potentes para lograr el resultado deseado.

    La mayoría de los programas de línea de comandos que operan en archivos también pueden aceptar la entrada en entrada estándar (entrada a través del teclado) y salida a salida estándar (impresión en
    pantalla).

    Algunos comandos están diseñados para operar solo dentro de una tubería y no pueden operar en archivos directamente.

    por ejemplo trcomando

  ls -C | tr 'a-z' 'A-Z'
    cmd1 | cmd2
  • Envía STDOUT de cmd1 a STDIN de cmd2 en lugar de la pantalla.

  • STDERR no se reenvía a través de las tuberías.

    En resumen Pipes is character (|)puede conectar comandos.

    Cualquier comando que escriba en STDOUT se puede usar en el lado izquierdo de la tubería.

       ls - /etc | less 

    Cualquier comando que se lea desde STDIN se puede usar en el lado derecho de una tubería.

       echo "test print" | lpr 

    Una tubería tradicional no tiene nombre porque existe de forma anónima y persiste solo mientras el proceso se esté ejecutando. Una tubería con nombre es persistente en el sistema y existe más allá de la vida del proceso y debe eliminarse una vez que ya no se usa. Los procesos generalmente se unen a la tubería con nombre (generalmente aparece como un archivo) para realizar la comunicación entre procesos (IPC).

fuente: http://en.wikipedia.org/wiki/Named_pipe


3

Para complementar las otras respuestas ...

stdin y stdout son descriptores de archivos y se leen y escriben como si fueran archivos. por lo tanto, puede hacerlo echo hi | grep hi, y reemplazará stdout de echo con una tubería y reemplazará stdin de grep al otro extremo de esta tubería.


1

Todo es un archivo

Si tomamos la frase demasiado literalmente, terminaríamos con el significado de "solo tenemos archivos y nada más". Esta no es la interpretación correcta, entonces cuál es.

Cuando decimos "Todo es un archivo", no estamos diciendo que todo esté almacenado en un disco. Estamos diciendo que todo parece un archivo, se puede leer, se puede escribir.

En Unix, una vez que se abre un archivo o no archivo, puede tratarse como un archivo. Sin embargo, no todos los archivos admiten todas las operaciones. Por ejemplo, algunos archivos (que no son archivos) no son compatibles con la búsqueda: deben leerse / escribirse en secuencia (esto es cierto para tuberías y tomas).

Todo tiene un nombre de archivo (en algunos sistemas: por ejemplo, Debian Gnu / Linux y muchos otros Gnu / Linux).

  • Todos los archivos abiertos tienen un nombre de archivo. Ver/proc/self/fd/…
  • Conectores de red se pueden abrir con un nombre de archivo, véase /dev/tcp
    por ejemplo,cat </dev/tcp/towel.blinkenlights.nl/23

Esa última parte solo es válida en sistemas con un /procsistema de archivos, y en sistemas (o shells) que proporcionan una /dev/tcpestructura de archivos.
Kusalananda
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.