Los canales que se utilizan en la comunicaci´on entre procesos en el n´ucleo monopuesto son del tipo buz´on, por lo tanto N procesos pueden enviar datos o solicitar peticiones de servicio a un mismo proceso receptor a trav´es del mismo canal.
El proceso general de utilizaci´on de los canales es el siguiente: Creaci´on del canal, env´ıo o recepci´on de informaci´on por el canal y liberaci´on del canal una vez que ya no se va a utilizar. La comunicaci´on que se utiliza es s´ıncrona, por lo tanto, cuando un proceso intenta comunicar con otro, enviar o recibir datos, queda bloqueado hasta que la comunicaci´on se ha completado. A continuaci´on se explican las primitivas que se han realizado para permitir la creaci´on y el uso de canales.
La creaci´on de un nuevo canal de comunicaciones se realiza a trav´es de la funci´on InitChannel.
InitChannel ((* out *) VAR ChannelType; (* in *) PortType)
El par´ametro de entrada es el puerto de comunicaciones por el que se va a realizar la comunicaci´on, como ´esta se basa en buzones, el puerto es en este caso el n´umero del buz´on que se va a utilizar. Antes de crear el canal hay que saber que puerto se va a utilizar. Como resultado de la ejecuci´on de la sentencia InitChannel se devuelve el
4.6. Canales
identificador del buz´on que se utilizar´a como canal de comunicaciones para enviar y recibir mensajes.
La funci´on InitChannel normalmente es realizada por el proceso padre antes de lanzar los procesos hijo que utilizar´an estos canales. Los procesos hijo heredan todos los canales creados por el proceso padre. La funci´on debe realizarse una vez para la creaci´on de los canales, ya que nuevas ejecuciones de la funci´on lo ´unico que har´ıa ser´ıa hacer copias del buz´on ya creado, no es como en el caso del n´ucleo distribuido que varias ejecuciones de la funci´on InitChannel crear´ıa canales distintos.
La asignaci´on de los puertos se puede realizar est´atica o din´amicamente. La asigna- ci´on est´atica se realiza cuando el valor del puerto es una constante y ´este ser´a siempre el mismo para todas las ejecuciones de la aplicaci´on. La asignaci´on es din´amica cuando el valor del puerto es una variable que toma un valor antes de ejecutar la sentencia InitChannel. Para realizar la asignaci´on din´amica de puertos hay que disponer de un proceso gestor de puertos, este proceso tiene asignados un rango de puertos disponi- bles para la aplicaci´on y los distribuye entre los diferentes procesos que van a crear canales. Cuando un proceso quiere crear un canal, solicita un puerto al gestor y ´este le proporciona uno de los que est´en libres.
Una vez que se ha creado el canal, antes de que sea utilizable, el proceso receptor debe tomar posesi´on del canal para poder recibir mensajes a trav´es de ´el. S´olo el proceso propietario del canal puede recibir por el canal, mientras que procesos emisores puede haber tantos como se quiera. Para ello el proceso receptor debe ejecutar la sentencia: GetChannel ((* in/out *) VAR ChannelType)
Una vez el proceso receptor ha tomado posesi´on del canal, el canal est´a listo para recibir. El propietario del canal podr´a recibir haciendo uso de la primitiva Receive. Receive ((* in *) VAR ChannelType; (* out *) VAR mensaje: ARRAY OF BYTE)
Esta instrucci´on permite la recepci´on de un mensaje a trav´es de un canal, el mensaje se almacena en el argumento de salida que podr´a ser de cualquier tipo, permiti´endose as´ı la transmisi´on de cualquier tipo de mensajes. La instrucci´on Receive bloquea la ejecuci´on del proceso hasta que se recibe un mensaje por el canal, es decir, la recepci´on es s´ıncrona.
Para realizar el env´ıo de mensajes se utiliza la sentencia Send:
Send ((* in *) VAR ChannelType; (* in *) mensaje: ARRAY OF BYTE)
La sentencia Send permite enviar cualquier tipo de mensaje a trav´es del canal, por esta raz´on se utiliza un argumento de tipo “array of byte” como par´ametro de entra- da, ya que se ajusta a cualquier tipo de argumento. Como la comunicaci´on es s´ıncrona, la sentencia Send tambi´en bloquea la ejecuci´on hasta que la transmisi´on se ha completado. El proceso emisor sabe si el proceso receptor ha recibido el mensaje porque el receptor le env´ıa internamente un mensaje de retorno como resultado de la transmisi´on.
Cap´ıtulo 4. EL N ´UCLEO MONOPUESTO INITCHANNEL (CAN1); COBEGIN PROCESO A; PROCESO B; COEND; BEGIN SEND (CAN1,MSG); BEGIN GETCHANNEL (CAN1); RECEIVE (CAN1,MSG); BUZON CAN1 COMUNICACIÓN MEDIANTE BOZONES PROCESO PRINCIPAL PROCESO A PROCESO A INITCHANNEL (CAN1); COBEGIN PROCESO A; PROCESO B; COEND; BEGIN SEND (CAN1,MSG); BEGIN GETCHANNEL (CAN1); RECEIVE (CAN1,MSG); BUZON CAN1 COMUNICACIÓN MEDIANTE BOZONES PROCESO PRINCIPAL PROCESO A PROCESO A
Figura 4.2: Comunicaci´on en el n´ucleo monopuesto
El mecanismo de comunicaciones en el n´ucleo monopuesto que reflejado por la figura 4.2. El c´odigo que se utiliza es simb´olico y se explica en el cap´ıtulo 6 al hablar de un posible esquema de traducci´on para el DD-Modula.
Cuando se termina la comunicaci´on y el canal ya no se va a utilizar m´as, el proceso receptor puede liberar el canal de comunicaciones mediante la ejecuci´on de la primitiva ReleaseChannel:
ReleaseChannel ((* in/out *) VAR ChannelType)
Una vez que se ha ejecutado la funci´on ReleaseChannel, si se quiere volver a utilizar el canal es necesario crear de nuevo el canal como si fuera nuevo.