stringtranslate.com

Tubería (Unix)

Una canalización de tres procesos de programa ejecutados en una terminal de texto

En los sistemas operativos informáticos tipo Unix , una canalización es un mecanismo para la comunicación entre procesos mediante el paso de mensajes. Una tubería 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 primer proceso aún se está ejecutando y se ejecutan simultáneamente . El concepto de tuberías fue defendido por Douglas McIlroy en los Laboratorios Bell , el hogar ancestral de Unix , durante el desarrollo de Unix, dando forma a su filosofía de caja de herramientas . [1] [2] Se denomina así por analogía a una tubería física . Una característica clave de estos oleoductos es su "ocultamiento de partes internas" (Ritchie y Thompson, 1974). Esto a su vez permite una mayor claridad y simplicidad en el sistema.

Este artículo trata sobre canalizaciones anónimas , donde los datos escritos por un proceso son almacenados en el sistema operativo hasta que son leídos por el siguiente proceso, y este canal unidireccional desaparece cuando se completan los procesos. Esto difiere de las canalizaciones con nombre , donde los mensajes se pasan hacia o desde una canalización a la que se le asigna un nombre convirtiéndola en un archivo y permanece después de que se completan los procesos. La sintaxis de shell estándar para canalizaciones anónimas es enumerar varios comandos, separados por barras verticales ("canalizaciones" en la palabrería común de Unix):

comando1 | comando2 | comando3    

Por ejemplo, para enumerar archivos en el directorio actual ( ls ), conservar solo las líneas de salida de ls que contienen la cadena "key" ( grep ) y ver el resultado en una página de desplazamiento ( less ), un usuario escribe lo siguiente en el línea de comando de una terminal:

ls  -l | clave grep | menos     

El comando ls -lse ejecuta como un proceso, cuya salida (stdout) se canaliza a la entrada (stdin) del proceso para grep key; y lo mismo para el proceso de less. Cada proceso toma información del proceso anterior y produce resultados para el siguiente proceso a través de flujos estándar . Cada uno |le dice 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 tubería (anónima) , implementada en el sistema operativo. Las tuberías son unidireccionales; los datos fluyen a través de la tubería de izquierda a derecha.

Ejemplo

A continuación se muestra un ejemplo de canalización que implementa una especie 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://en.wikipedia.org/wiki/Pipeline_(Unix)/Pipeline_(Unix)" |  sed 's/[^a-zA-Z ]/ /g' |  tr 'AZ ' 'az\n' |   grep '[az]' |  ordenar  -u | comm  -23  -  < ( ordenar  /usr/share/dict/palabras ) | 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, por 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 solo líneas que contienen al menos un carácter alfabético en minúscula (eliminando las líneas en blanco).
  5. sortordena la lista de 'palabras' en orden alfabético y el -umodificador elimina los duplicados.
  6. commbusca 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 aquellas que se encuentran únicamente en el primer archivo nombrado. El -lugar de un nombre de archivo hace commque se utilice su entrada estándar (de la tubería 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 (mediante 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.

Canalizaciones en interfaces de línea de comando

Todos los shells de Unix ampliamente utilizados tienen una construcción de sintaxis especial para la creación de canalizaciones. En todos los usos, uno escribe los comandos en secuencia, separados por el carácter de barra vertical ASCII (que, por esta razón, a menudo se denomina "carácter de barra vertical"). El shell inicia los procesos y organiza las conexiones necesarias entre sus flujos estándar (incluida cierta cantidad de almacenamiento en búfer ). |

Flujo de errores

De forma predeterminada, los flujos de error estándar (" stderr ") de los procesos en una tubería no pasan a través de la tubería; en cambio, 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 |&desde la versión 4.0 [3] o usar 2>&1, así como redirigirlo a un archivo diferente.

molino de tubos

En las canalizaciones 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, usando un llamado molino o molino de tuberías (ya que un whilecomando se usa para "fresar" los resultados del comando inicial). Esta construcción generalmente se parece a:

comando | mientras lee -r var1 var2 ... ; hacer # procesar cada línea, usando variables analizadas 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 ciclo while; algunos shells, como zsh y más nuevos # versiones del shell Korn, procese los comandos a la izquierda del operador de tubería # en un subshell) hecho              

Es posible que dicho molino de tuberías no funcione según lo previsto si el cuerpo del bucle incluye comandos, como caty ssh, que se leen desde stdin: [4] en la primera iteración del bucle, dicho programa (llamémoslo drenaje ) leerá la salida restante de command, y el bucle terminará (los resultados dependerán de las características específicas del drenaje). Hay un par de formas posibles de evitar este comportamiento. Primero, algunos drenajes admiten una opción para deshabilitar la lectura stdin(por ejemplo ssh -n, ). Alternativamente, si el drenaje no necesita leer ninguna entrada stdinpara hacer algo útil, se puede proporcionar < /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 variables al entorno externo del shell. Para solucionar este problema, el "pipemill" se puede alimentar desde un documento aquí que contiene un comando de sustitución , que espera a que la canalización termine de ejecutarse antes de analizar el contenido. Alternativamente, se puede utilizar una canalización con nombre o una sustitución de proceso para la ejecución paralela. GNU bash también tiene una lastpipeopción para deshabilitar la bifurcación para el último componente de tubería. [5]

Crear canalizaciones mediante programación

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

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

Las canalizaciones con nombre también se pueden crear usandomkfifo()omknod()y luego presentarse como archivo de entrada o salida a los programas a medida que se invocan. Permiten crear canalizaciones de múltiples rutas y son especialmente eficaces cuando se combinan con la redirección de errores estándar o contee.

Implementación

En la mayoría de los sistemas tipo Unix, todos los procesos de una canalización se inician al mismo tiempo, con sus flujos conectados adecuadamente y gestionados por el programador junto con todos los demás procesos que se ejecutan en la máquina. Un aspecto importante de esto, que distingue a los pipes de Unix de otras implementaciones de pipes, es el concepto de almacenamiento en búfer : por ejemplo, un programa emisor puede producir 5000 bytes por segundo , y un programa receptor sólo puede aceptar 100 bytes por segundo, pero no Se pierden datos. En cambio, la salida del programa emisor se mantiene en el búfer. Cuando el programa receptor está listo para leer datos, el siguiente programa en la canalización lee del búfer. Si el búfer está lleno, el programa emisor se detiene (bloquea) hasta que el receptor elimina al menos algunos datos del búfer. En Linux, el tamaño del búfer es de 65.536 bytes (64 KB). Un filtro de terceros de código abierto llamado bfr está disponible para proporcionar buffers más grandes si es necesario.

Tuberías de red

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

Historia

El concepto de canalización fue inventado por Douglas McIlroy [6] y descrito por primera vez en las páginas de manual de la Versión 3 de Unix . [7] [8] McIlroy notó que la mayor parte del tiempo los shells de comandos pasaban el archivo de salida de un programa como entrada a otro.

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, "vio una orgía inolvidable de frases ingeniosas en las que todos se unieron a la emoción de la plomería". McIlroy también le da crédito a Thompson por la |notación, que simplificó enormemente la descripción de la sintaxis de canalización en la Versión 4 . [9] [7]

Aunque se desarrollaron de forma independiente, los pipes de Unix están relacionados y fueron precedidos por los 'archivos de comunicación' desarrollados por Ken Lochner [10] en la década de 1960 para el Dartmouth Time Sharing System . [11]

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

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

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 finalmente llegó a denominarse patrón de diseño de tuberías y filtros de ingeniería de software .

Ver también

Referencias

  1. ^ Mahoney, Michael S. "El proyecto de historia oral de Unix: versión.0, el comienzo". McIlroy: Era uno de los únicos lugares donde casi ejercía control administrativo sobre Unix, estaba presionando para lograr esas cosas, sí.
  2. ^ "Petroglifos proféticos". cm.bell-labs.com . Archivado desde el original el 8 de mayo de 1999 . Consultado el 22 de mayo de 2022 .
  3. ^ "Notas de la versión de Bash". eswww.case.edu . Consultado el 14 de junio de 2017 .
  4. ^ "Interacción de Shell Loop con SSH". 6 de marzo de 2012. Archivado desde el original el 6 de marzo de 2012.
  5. ^ Juan1024. "¿Cómo puedo almacenar los resultados del comando" buscar "como una matriz en Bash"? Desbordamiento de pila .{{cite web}}: Mantenimiento CS1: nombres numéricos: lista de autores ( enlace )
  6. ^ "La creación del sistema operativo UNIX". Laboratorios Bell. Archivado desde el original el 14 de septiembre de 2004.
  7. ^ ab McIlroy, MD (1987). Un lector de Research Unix: extractos comentados del Manual del programador, 1971-1986 (PDF) (Informe técnico). CSTR. Laboratorios Bell. 139.
  8. ^ Thompson K , Ritchie DM (febrero de 1973). Manual del programador de UNIX, tercera edición (PDF) (Informe técnico) (3ª ed.). Laboratorios Bell. pag. 178.
  9. ^ "Tuberías: una breve introducción". El proyecto de información de Linux. 23 de agosto de 2006 [Creado el 29 de abril de 2004] . Consultado el 7 de enero de 2024 .
  10. ^ "Tiempo compartido en Dartmouth" (DOC) . Instituto de Tecnología de Rochester . Consultado el 7 de enero de 2024 .
  11. ^ "Datos". cm.bell-labs.com . Archivado desde el original el 20 de febrero de 1999 . Consultado el 22 de mayo de 2022 .
  12. ^ Cox, Russ. "Subprocesos Bell Labs y CSP". Centralita . Consultado el 7 de enero de 2024 .

enlaces externos