Tubería (Unix)

Mecanismo de comunicación entre procesos mediante paso de mensajes
Una tubería de tres procesos de programa que se ejecutan en una terminal de texto

En los sistemas operativos de tipo Unix , una canalización es un mecanismo de comunicación entre procesos mediante el paso de mensajes. Una canalización es un conjunto de procesos encadenados entre sí por sus flujos estándar , de modo que el texto de salida de cada proceso ( stdout ) se pasa directamente como entrada ( stdin ) al siguiente. El segundo proceso se inicia mientras el primero todavía se está ejecutando, y se ejecutan simultáneamente .

El concepto de pipelines fue defendido por Douglas McIlroy en Bell Labs , la casa ancestral de Unix , durante el desarrollo de Unix, dando forma a su filosofía de caja de herramientas . Se lo denomina así por analogía con un pipeline físico . Una característica clave de estos pipelines es que "ocultan los elementos internos". Esto, a su vez, permite una mayor claridad y simplicidad en el sistema.

Las tuberías de la tubería son tuberías anónimas (a diferencia de las tuberías con nombre ), donde los datos escritos por un proceso se almacenan en el búfer del sistema operativo hasta que son leídos por el siguiente proceso, y este canal unidireccional desaparece cuando se completan los procesos. La sintaxis estándar del shell para las tuberías anónimas es enumerar varios comandos, separados por barras verticales (" tuberías " en el lenguaje común de Unix).

Historia

El concepto de pipeline fue inventado por Douglas McIlroy [1] y descrito por primera vez en las páginas de manual de la versión 3 de Unix . [2] [3] McIlroy se dio cuenta de que la mayor parte del tiempo los shells de comandos pasaban el archivo de salida de un programa como entrada a otro. El concepto de pipelines fue defendido por Douglas McIlroy en la casa ancestral de Unix , Bell Labs , durante el desarrollo de Unix, dando forma a su filosofía de caja de herramientas . [4] [5]

Sus ideas se implementaron en 1973 cuando ("en una noche febril", escribió McIlroy) Ken Thompson agregó la pipe()llamada al sistema y las tuberías al shell y varias utilidades en la versión 3 de Unix. "Al día siguiente", continuó McIlroy, "vimos una orgía inolvidable de frases ingeniosas mientras todos se unían a la emoción de la plomería". McIlroy también le atribuye a Thompson la |notación, que simplificó enormemente la descripción de la sintaxis de las tuberías en la versión 4. [ 6] [2]

Aunque se desarrollaron de forma independiente, las tuberías de Unix están relacionadas con, y fueron precedidas por, los "archivos de comunicación" desarrollados por Ken Lochner [7] en la década de 1960 para el Sistema de tiempo compartido de Dartmouth . [8]

Otros sistemas operativos

Esta característica de Unix fue tomada prestada por otros sistemas operativos, como MS-DOS y el paquete CMS Pipelines en VM/CMS y MVS , y eventualmente llegó a ser designada como el patrón de diseño de tuberías y filtros de la ingeniería de software .

Desarrollo adicional del concepto

En los procesos secuenciales de comunicación (CSP) de Tony Hoare , las tuberías de McIlroy se desarrollan aún más. [9]

Implementación

Un mecanismo de pipeline se utiliza para la comunicación entre procesos mediante el paso de mensajes. Un pipeline es un conjunto de procesos encadenados entre sí por sus flujos estándar , de modo que el texto de salida de cada proceso ( stdout ) se pasa directamente como entrada ( stdin ) al siguiente. El segundo proceso se inicia mientras el primero todavía se está ejecutando, y se ejecutan simultáneamente . Se denomina así por analogía a un pipeline físico . Una característica clave de estos pipelines es su "ocultamiento de los elementos internos". [10] Esto, a su vez, permite una mayor claridad y simplicidad en el sistema.

En la mayoría de los sistemas tipo Unix, todos los procesos de una tubería se inician al mismo tiempo, con sus flujos conectados apropiadamente y administrados por el planificador junto con todos los demás procesos que se ejecutan en la máquina. Un aspecto importante de esto, que distingue a las tuberías de Unix de otras implementaciones de tuberías, es el concepto de almacenamiento en búfer : por ejemplo, un programa de envío puede producir 5000 bytes por segundo , y un programa receptor puede solo ser capaz de aceptar 100 bytes por segundo, pero no se pierden datos. En cambio, la salida del programa de envío se mantiene en el búfer. Cuando el programa receptor está listo para leer datos, el siguiente programa en la tubería lee desde el búfer. Si el búfer está lleno, el programa de envío se detiene (se bloquea) hasta que el receptor elimine al menos algunos datos del búfer. En Linux, el tamaño del búfer es de 65.536 bytes (64 KiB). Hay disponible un filtro de terceros de código abierto llamado bfr para proporcionar búferes más grandes si es necesario.

Tuberías de red

Herramientas como netcat y socat pueden conectar tuberías a sockets TCP/IP .

Canalizaciones en interfaces de línea de comandos

Todos los shells de Unix de uso generalizado tienen una sintaxis especial para la creación de pipelines. En todos los casos, los comandos se escriben en secuencia, separados por el carácter de barra vertical ASCII (que, por este motivo, suele denominarse "carácter de canalización"). El shell inicia los procesos y organiza las conexiones necesarias entre sus flujos estándar (incluida cierta cantidad de almacenamiento en búfer ).|

El pipeline utiliza canales anónimos . En el caso de los canales anónimos, los datos escritos por un proceso se almacenan en el búfer del sistema operativo hasta que son leídos por el siguiente proceso, y este canal unidireccional desaparece cuando se completan los procesos; esto difiere de los canales con nombre , en los que los mensajes se pasan hacia o desde un canal que se nombra convirtiéndolo en un archivo, y permanece después de que se completan los procesos. La sintaxis estándar del shell para los canales anónimos es enumerar varios comandos, separados por barras verticales ("canales" en el lenguaje común de Unix):

comando1 | comando2 | comando3    

Por ejemplo, para listar archivos en el directorio actual ( ls ), retener sólo las líneas de salida de ls que contienen la cadena "clave" ( grep ) y ver el resultado en una página desplazable ( less ), un usuario escribe lo siguiente en la línea de comando de una terminal:

ls  -l | grep clave | menos     

El comando ls -lse ejecuta como un proceso, cuya salida (stdout) se canaliza a la entrada (stdin) del proceso for grep key; y lo mismo ocurre con el proceso for less. Cada proceso toma la entrada del proceso anterior y produce la salida para el siguiente proceso a través de flujos estándar . Cada uno |le indica al shell que conecte la salida estándar del comando de la izquierda con la entrada estándar del comando de la derecha mediante un mecanismo de comunicación entre procesos llamado canalización (anónimo) , implementado en el sistema operativo. Las canalizaciones son unidireccionales; los datos fluyen a través de la canalización de izquierda a derecha.

Ejemplo

A continuación se muestra un ejemplo de una secuencia de comandos que implementa un tipo de corrector ortográfico para el recurso web indicado por una URL . A continuación se ofrece una explicación de lo que hace.

curl "https://es.wikipedia.org/wiki/Pipeline_(Unix)" |  sed 's/[^a-zA-Z ]/ /g' |  es 'AZ' 'az\n' |   grep '[az]' |  ordenar  -u | comm  -23  -  < ( ordenar  /usr/share/dict/words ) | menos
  1. curlobtiene el contenido HTML de una página web (podría usarse wgeten algunos sistemas).
  2. sedreemplaza todos los caracteres (del contenido de la página web) que no sean espacios o letras, con espacios. ( Se conservan las nuevas líneas ).
  3. trcambia todas las letras mayúsculas a minúsculas y convierte los espacios en las líneas de texto en nuevas líneas (cada 'palabra' ahora está en una línea separada).
  4. grepincluye sólo líneas que contienen al menos un carácter alfabético en minúscula (eliminando cualquier línea en blanco).
  5. sortordena la lista de 'palabras' en orden alfabético y el -uconmutador elimina los duplicados.
  6. commencuentra líneas en común entre dos archivos, -23suprime las líneas exclusivas del segundo archivo y las que son comunes a ambos, dejando solo las que se encuentran solo en el primer archivo nombrado. El -en lugar de un nombre de archivo hace commque se use su entrada estándar (de la línea de canalización en este caso). sort /usr/share/dict/wordsordena el contenido del wordsarchivo alfabéticamente, como commse espera, y <( ... )envía los resultados a un archivo temporal (a través de la sustitución de procesos ), que commlee. El resultado es una lista de palabras (líneas) que no se encuentran en /usr/share/dict/words.
  7. lessPermite al usuario navegar a través de los resultados.

Flujo de error

De manera predeterminada, los flujos de error estándar (" stderr ") de los procesos en una tubería no se pasan a través de la tubería; en su lugar, se fusionan y se dirigen a la consola . Sin embargo, muchos shells tienen una sintaxis adicional para cambiar este comportamiento. En el shell csh , por ejemplo, usar |&en lugar de |significa que el flujo de error estándar también debe fusionarse con la salida estándar y enviarse al siguiente proceso. El shell Bash también puede fusionar el error estándar con |&desde la versión 4.0 [11] o usando 2>&1, así como redirigirlo a un archivo diferente.

Molino de tubos

En las tuberías simples más utilizadas, el shell conecta una serie de subprocesos a través de tuberías y ejecuta comandos externos dentro de cada subproceso. Por lo tanto, el shell en sí no realiza ningún procesamiento directo de los datos que fluyen a través de la tubería.

Sin embargo, es posible que el shell realice el procesamiento directamente, utilizando un denominado molino o pipemill (ya que se utiliza un whilecomando para "moler" los resultados del comando inicial). Esta construcción generalmente se parece a algo como esto:

command | while read -r var1 var2 ... ; do # procesa cada línea, usando variables como se analizan en var1, var2, etc. # (tenga en cuenta que esto puede ser un subshell: var1, var2, etc. no estarán disponibles # después de que finalice el bucle while; algunos shells, como zsh y versiones más nuevas de Korn shell, procesan los comandos a la izquierda del operador de tubería # en un subshell) done              

Es posible que un pipemill de este tipo no funcione como se espera si el cuerpo del bucle incluye comandos, como caty ssh, que leen desde stdin: [12] en la primera iteración del bucle, un programa de este tipo (llamémoslo el drenaje ) leerá la salida restante de command, y el bucle luego terminará (con resultados que dependen de los detalles del drenaje). Hay un par de formas posibles de evitar este comportamiento. Primero, algunos drenajes admiten una opción para deshabilitar la lectura de stdin(por ejemplo, ssh -n). Alternativamente, si el drenaje no necesita leer ninguna entrada de stdinpara hacer algo útil, se puede dar < /dev/nullcomo entrada.

Como todos los componentes de una tubería se ejecutan en paralelo, un shell normalmente bifurca un subproceso (un subshell) para manejar su contenido, lo que hace imposible propagar cambios de variables al entorno del shell externo. Para solucionar este problema, el "pipemill" puede alimentarse en cambio desde un documento here que contenga una sustitución de comando , que espera a que la tubería termine de ejecutarse antes de procesar el contenido. Alternativamente, se puede utilizar una tubería con nombre o una sustitución de proceso para la ejecución en paralelo. GNU bash también tiene una lastpipeopción para deshabilitar la bifurcación para el último componente de la tubería. [13]


Creación de pipelines mediante programación

Las tuberías se pueden crear bajo el control del programa. La pipe() llamada al sistema Unix solicita al sistema operativo que construya un nuevo objeto de tubería anónimo . Esto da como resultado dos descriptores de archivo nuevos y abiertos en el proceso: el extremo de solo lectura de la tubería y el extremo de solo escritura. Los extremos de la tubería parecen ser descriptores de archivo anónimos normales , excepto que no tienen capacidad de búsqueda.

Para evitar bloqueos y aprovechar el paralelismo, el proceso Unix con una o más tuberías nuevas generalmente llamará fork()para crear nuevos procesos. Luego, cada proceso cerrará los extremos de la tubería que no usará antes de producir o consumir datos. Alternativamente, un proceso podría crear nuevos subprocesos y usar la tubería para comunicarse entre ellos.

También se pueden crear canales con nombremkfifo() utilizando omknod()y luego se presentan como archivo de entrada o salida a los programas a medida que se los invoca. Permiten crear canales de múltiples rutas y son especialmente eficaces cuando se combinan con la redirección de error estándar o contee.

El robot en el ícono de Automator de Apple , que también utiliza un concepto de tubería para encadenar comandos repetitivos, sostiene una tubería en homenaje al concepto original de Unix.

Véase también

Referencias

  1. ^ "La creación del sistema operativo UNIX". Bell Labs. Archivado desde el original el 14 de septiembre de 2004.
  2. ^ ab McIlroy, MD (1987). Un lector de Unix para investigación: extractos anotados del Manual del programador, 1971–1986 (PDF) (Informe técnico). CSTR. Bell Labs. 139.
  3. ^ Thompson K , Ritchie DM (febrero de 1973). Manual del programador de UNIX, tercera edición (PDF) (informe técnico) (3.ª ed.). Bell Labs. pág. 178.
  4. ^ Mahoney, Michael S. "El proyecto de historia oral de Unix: Release.0, el comienzo". McIlroy: Fue uno de los pocos lugares donde casi ejercí un control administrativo sobre Unix, estaba presionando para que se hicieran esas cosas, sí.
  5. ^ "Petroglifos proféticos". www.bell-labs.com . Archivado desde el original el 8 de mayo de 1999. Consultado el 22 de mayo de 2022 .
  6. ^ "Pipes: una breve introducción". The Linux Information Project. 23 de agosto de 2006 [Creado el 29 de abril de 2004] . Consultado el 7 de enero de 2024 .
  7. ^ "Dartmouth Timesharing" (DOC) . Instituto Tecnológico de Rochester . Consultado el 7 de enero de 2024 .
  8. ^ "Datos". www.bell-labs.com . Archivado desde el original el 20 de febrero de 1999 . Consultado el 22 de mayo de 2022 .
  9. ^ Cox, Russ. "Bell Labs y CSP Threads". Swtchboard . Consultado el 7 de enero de 2024 .
  10. ^ Ritchie y Thompson, 1974
  11. ^ "Notas de la versión de Bash". tiswww.case.edu . Consultado el 14 de junio de 2017 .
  12. ^ "Interacción de bucle de shell con SSH". 6 de marzo de 2012. Archivado desde el original el 6 de marzo de 2012.
  13. ^ John1024. "¿Cómo puedo almacenar los resultados del comando "find" como una matriz en Bash?". Desbordamiento de pila .{{cite web}}: CS1 maint: nombres numéricos: lista de autores ( enlace )
  • Historia de la notación pipe de Unix Archivado el 8 de abril de 2015 en Wayback Machine
    • Memorándum original de Doug McIlroy de 1964, proponiendo el concepto de una tubería por primera vez
  • pipe: crear un canal entre procesos – Referencia de interfaces del sistema, La especificación única de UNIX , versión 4 de The Open Group
  • Pipes: una breve introducción por The Linux Information Project (LINFO)
  • Unix Pipes: un paradigma de programación potente y elegante (Softpanorama)
  • Análisis de datos ad hoc desde la línea de comandos de Unix en Wikilibros: muestra cómo utilizar canalizaciones compuestas de filtros simples para realizar análisis de datos complejos.
  • Uso y abuso de tuberías con datos de audio: ofrece una introducción al uso y abuso de tuberías con netcat, nettee y fifos para reproducir audio a través de una red.
  • stackoverflow.com – Preguntas y respuestas sobre el manejo de pipelines de bash.
Obtenido de "https://es.wikipedia.org/w/index.php?title=Pipeline_(Unix)&oldid=1241386261"