En informática, un canal es un modelo para la comunicación entre procesos y la sincronización mediante el paso de mensajes . Un mensaje puede enviarse a través de un canal y otro proceso o subproceso puede recibir mensajes enviados a través de un canal al que tiene una referencia , como un flujo . Las diferentes implementaciones de canales pueden almacenarse en búfer o no, y pueden ser síncronas o asíncronas.
Los canales son fundamentales para el enfoque de cálculo de procesos de la concurrencia y se originaron en la comunicación de procesos secuenciales (CSP), un modelo formal para la concurrencia, y se han utilizado en muchos lenguajes derivados, como occam y el lenguaje de programación Limbo (a través de Newsqueak y Alef lenguaje de programación ). También se utilizan en Plan 9 de libthread de Bell Labs , así como en Stackless Python y el lenguaje de programación Go .
Implementaciones de canal
Los canales modelados según el modelo CSP son inherentemente síncronos : un proceso que espera recibir un objeto de un canal se bloqueará hasta que se envíe el objeto. Esto también se denomina comportamiento de encuentro . Las operaciones típicas admitidas se presentan a continuación utilizando el ejemplo de la API del canal libthread .
- Creación de canales de tamaño fijo o variable, devolviendo una referencia o manejador
Canal * chancreate ( int elemsize , int bufsize )
- enviando a un canal
int chansend ( canal * c , void * v )
- recibir de un canal
int chanrecv ( Canal * c , void * v )
canales libthread
La biblioteca de subprocesos múltiples , libthread , que se creó por primera vez para el sistema operativo Plan 9 , ofrece comunicación entre subprocesos basada en canales de tamaño fijo.
Eventos OCaml
El módulo de eventos OCaml ofrece canales escritos para sincronización. Cuando se llaman las funciones de envío y recepción del módulo, crean los eventos de envío y recepción correspondientes que se pueden sincronizar.
Ejemplos de
Lua Love2D
La biblioteca Love2D , que es parte del lenguaje de programación Lua , implementa canales con operaciones push y pop similares a las pilas. La operación emergente se bloqueará siempre que haya datos residentes en la pila. Una operación de demanda es equivalente a pop, excepto que se bloqueará hasta que haya datos en la pila.
- Una cadena que contiene código que será interpuesto por una función como cadena de carga (), - pero en el lado C para iniciar un hilo nativo. threadCode local = [[ love.thread.getChannel ("prueba"): push ("¡Hola mundo!") ]]función amor . load () : inicia el hilo. hilo = amor . hilo . newThread ( threadCode ) hilo : start () - El hilo se bloqueará hasta "¡Hola mundo!" se saca de la pila de prueba del canal. - Debido a que el canal se puede extraer antes de que se ejecute el hilo por primera vez, es posible que no haya datos en la pila. - en ese caso, use: demand () en lugar de: pop () porque: demand () se bloqueará hasta que haya datos en la pila y luego devolverá los datos. print ( love . thread . getChannel ( "test" ): demand ()) - El hilo ahora puede terminar. final
XMOS XC
El lenguaje de programación XMOS XC proporciona un tipo primitivo "chan" y dos operadores "<:" y ":>" para enviar y recibir datos de un canal. [1]
En este ejemplo, dos subprocesos de hardware se inician en el XMOS, ejecutando las dos líneas en el bloque "par". La primera línea transmite el número 42 a través del canal mientras que la segunda espera hasta que se recibe y establece el valor de x. El lenguaje XC también permite la recepción asíncrona en canales a través de una declaración de selección.
chan c ; int x ; par { c <: 42 ; c :> x ; }
Ir
Este fragmento de código Go funciona de manera similar al código XC. Primero se crea el canal c, luego se genera una goroutine que envía 42 a través del canal. Cuando el número se coloca en el canal x se establece en 42. Go permite que los canales almacenen en búfer el contenido, así como no bloqueen la recepción mediante el uso de un bloque de selección. [2]
c : = hacer ( chan int )ir a func () { c <- 42 } ()x : = <- c
Oxido
Rust proporciona canales asincrónicos para la comunicación entre subprocesos. Los canales permiten un flujo de información unidireccional entre dos puntos finales: el Sender
y el Receiver
. [3]
use std :: sync :: mpsc ; use std :: hilo ; fn main () { dejar ( tx , rx ) = mpsc :: canal (); thread :: spawn ( mover || { tx . enviar ( 123 ). desenvolver (); }); sea resultado = rx . recv (); println! ( "{:?}" , resultado ); }
Aplicaciones
Además de su uso fundamental para la comunicación entre procesos, los canales se pueden usar como una primitiva para implementar varias otras construcciones de programación concurrentes que se pueden realizar como flujos. Por ejemplo, los canales se pueden usar para construir futuros y promesas , donde un futuro es un canal de un elemento y una promesa es un proceso que envía al canal, cumpliendo el futuro. [4] De manera similar, los iteradores se pueden construir directamente a partir de canales. [5]
Lista de implementaciones
Lista de implementaciones de canales no estándar basadas en bibliotecas
- Para C ++:
- stlab [6] Esta implementación admite divisiones y diferentes operaciones de combinación y compresión. Se pueden adjuntar diferentes ejecutores a los nodos individuales.
Referencias
- ^ "Copia archivada" . Archivado desde el original el 4 de marzo de 2016 . Consultado el 10 de mayo de 2015 .CS1 maint: copia archivada como título ( enlace )
- ^ https://golang.org/doc/effective_go.html#channels
- ^ "Canales - Rust por ejemplo" . doc.rust-lang.org . Consultado el 28 de noviembre de 2020 .
- ^ " Futuros ", patrones de idioma de Go
- ^ " Iteradores ", patrones de idioma de Go
- ^ "stlab es el trabajo en curso de lo que fue el Laboratorio de Tecnología de Software de Adobe. Las bibliotecas de código fuente de Adobe (ASL), las bibliotecas de plataforma y las nuevas bibliotecas de stlab están alojadas en github" . 2021-01-31.
enlaces externos
- Implementación del canal Libthread
- Bell Labs y subprocesos de CSP
- Limbo - Programación de aplicaciones Inferno
- Stackless.com - Canales
- - Eventos OCaml