Documentos de Académico
Documentos de Profesional
Documentos de Cultura
GUÍA DE LABORATORIO
INFORMACIÓN BÁSICA
OBJETIVOS/TEMAS Y COMPETENCIAS
OBJETIVOS:
- Utilizar las funciones para comunicación entre procesos usando colas de mensajes
- Conocer el uso de colas de mensajes para la comunicación entre procesos en Linux
TEMAS:
• Uso de colas de mensajes para comunicación entre procesos
• Uso de programación concurrente para comunicación entre procesos
CONTENIDO DE LA GUÍA
I. MARCO CONCEPTUAL
Teoría de Colas de Mensajes
Cada proceso puede crear una o más estructuras llamadas colas; Cada estructura puede esperar uno o más
mensajes de diferentes tipos, que pueden venir de diferentes fuentes y pueden contener información de toda
naturaleza; todos pueden enviar un mensaje a las colas de las cuales conozcan su identificador. Los procesos
pueden acceder secuencialmente a la cola, leyendo los mensajes en orden cronológico (desde el más antiguo,
el primero, al más reciente, el último en llegar), pero selectivamente, esto es, considerando sólo los mensajes
de un cierto tipo: esta última característica nos da un tipo de control de la prioridad sobre los mensajes que
leemos.
El uso de las colas es similar a una implementación simple de un sistema de correo: cada proceso tiene una
dirección con la cual puede operar con otros procesos. El proceso puede entonces leer los mensajes
mandados a su dirección en un orden preferencial y actuando de acuerdo con lo que le ha sido notificado.
Antes de que podamos implementar el lenguaje C las colas de mensajes es necesario hablar sobre otro
problema relativo a la sincronización: la necesidad de un protocolo de comunicación.
Creando un protocolo
Un protocolo es un conjunto de reglas que controlan la interacción de los elementos en un conjunto. El uso de
las colas de mensajes nos permite implementar protocolos más complejos: es suficiente pensar que cada
protocolo de red (TCP/IP, DNS, SMTP, ...) está construido con una arquitectura de intercambio de mensajes,
incluso si la comunicación es entre ordenadores y no interna en uno de ellos. La comparación es compulsiva:
no hay ninguna diferencia real entre comunicación entre procesos en la misma máquina y comunicación
entre procesos entre distintas máquinas.
Este es un ejemplo sencillo de protocolo basado en intercambio de mensajes: dos procesos A y B se ejecutan
concurrentemente y procesan diferentes datos; una vez terminados sus procesos tienen que mezclar sus
resultados. Un protocolo simple para dirigir esta interacción puede ser el siguiente:
PROCESO B:
Trabaja con tus datos
Cuando termines mándale un mensaje a A
Cuando A responda empieza a enviarle tus resultados.
PROCESO A:
Trabaja con tus datos
Espera un mensaje de B
Responde al mensaje
Recibe los datos y mezclalos con los tuyos
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
Elegir qué proceso tiene que mezclar los datos es en este caso totalmente arbitrario; lo más común es que
esto se haga en función de la naturaleza de los procesos envueltos (cliente/servidor)
Este protocolo es sencillamente extensible al caso de n procesos : cada proceso menos A trabaja con sus
propios datos y luego envía un mensaje a A. Caundo A responde cada proceso le manda sus resultados: la
estructura del proceso individual (excepto A) no es modificada.
La estructura base del sistema que describe un mensaje se llama msgbuf ; y está declarada en linux/msg.h
struct message {
long mtype; /* message type */
long sender; /* sender id */
long receiver; /* receiver id */
struct info data; /* message content */
...
};
Para crear una nueva cola un proceso debe llamar a la función msgget()
(crea la cola, si no existe, y da acceso al propietario y grupo de usuarios), y este devuelve el identificador de
la cola.
Para enviar un mensaje a una cola de la cual conozcamos us identificador, tenemos que utilizar la función
msgsnd()
int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
Donde msqid es el identificador de la cola, msgp es un puntero al mensaje que tenemos que enviar (cuyo tipo
es aquí definido como struct msgbuf pero que es el tipo que redefinimos), msgsz la dimensión del mensaje
(excluyendo la longitud del tipo mtype que tiene la longitud de un long, que es normalmente de 4 bytes) y
msgflg un flag relativo a la política de espera. La longitud del mensaje puede ser facilmente encontrada
como
length = sizeof(struct message) - sizeof(long);
mientras la política de espera se refiere al caso de la cola completa: si msgflg es puesta a IPC_NOWAIT el
proceso emisor no esperará mientras no haya algún espacio disponible y saldrá con algún código de error ;
hablaremos sobre cada caso cuando hablemos del tratamiento de errores.
Para leer los mensjaes contenidos en una cola utilizamos la llamada del sistema msgrcv()
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msgflg)
Donde el puntero msgp identifica el búffer donde copiaremos el mensaje leido de la cola y mtype identica el
subconjunto de mensajes que queremos considerar.
Se puede eliminar una cola a través del uso de la primitiva msgctl() con el flag IPC_RMID
msgctl(qid, IPC_RMID, 0)
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct Msm {
long mtype;
int litros;
}Msm;
msm.litros = 10000*i;
msgsnd(msgid,&msm,sizeof(Msm)-sizeof(long),IPC_NOWAIT);
}
}
//
char buffer[12];
scanf("%s",buffer);
//liberar
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
Ejercicio 2.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo leer.c, compilelo:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
struct Msm {
long mtype;
int litros;
}Msm;
return 0;
}
Ejercicio 3.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo writer.c, compílelo
int main()
{
key_t key;
int msgid;
// y retorna el identificador
msgid = msgget(key, 0666 | IPC_CREAT);
message.mesg_type = 1;
return 0;
}
Ejercicio 4.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo reader.c, compílelo
int main()
{
key_t key;
int msgid;
return 0;
}
Ejercicio 5.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo msgg_send.c,
compílelo
int main(void) {
struct my_msgbuf buf;
int msqid;
int len;
key_t key;
system("touch msgq.txt");
Ejercicio 6.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo msgq_recv.c,
compílelo
long mtype;
char mtext[200];
};
int main(void) {
struct my_msgbuf buf;
int msqid;
int toend;
key_t key;
Ejercicio 7
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo elqueenvia.c,
compílelo
#include <stdio.h>
#include <stdlib.h>
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
#include <linux/ipc.h>
#include <linux/msg.h>
int main()
{
int qid;
key_t msgkey;
mess_t sent;
mess_t received;
int length;
/* Longitud el mensaje */
length = sizeof(mess_t) - sizeof(long);
msgkey = ftok(".",'m');
/* Crea la cola */
qid = msgget(msgkey, IPC_CREAT | 0660);
/* Construye el mensaje */
sent.mtype = 1;
sent.int_num = rand();
sent.float_num = (float)(rand())/3;
sent.ch = 'f';
/* Envia el mensaje */
msgsnd(qid, &sent, length, 0);
printf("MENSAJE ENVIADO...\n");
/* Recibe el mensaje */
msgrcv(qid, &received, length, sent.mtype, 0);
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
printf("MENSAJE RECIBIDO...\n");
/* Estruye la cola */
msgctl(qid, IPC_RMID, 0);
}
Ejercicio 8.
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo elquerecibe.c,
compílelo
#include <stdio.h>
#include <stdlib.h>
#include <linux/ipc.h>
#include <linux/msg.h>
#include <sys/types.h>
int main()
{
int qid;
key_t msgkey;
pid_t pid;
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
mess_t buf;
int length;
int cont;
msgkey = ftok(".",'m');
if(!(pid = fork())){
printf("HIJO - QID = %d\n", qid);
return 0;
}
return 0;
}
Ejercicio 9
UNIVERSIDAD NACIONAL DE SAN AGUSTIN
FACULTAD DE INGENIERÍA DE PRODUCCIÓN Y SERVICIOS
ESCUELA PROFESIONAL DE INGENIERÍA DE SISTEMA
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo message_send.c,
compílelo
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
/*
* Declara la estructura del mensaje.
*/
main()
{
int msqid;
int msgflg = IPC_CREAT | 0666;
key_t key;
message_buf sbuf;
size_t buf_length;
/*
* Consigue el id de la cola de mensaje para el
* "name" 1234, el cual ha sido creado
* por el servidor.
*/
key = 1234;
/*
* We'll send message type 1
*/
sbuf.mtype = 1;
buf_length = strlen(sbuf.mtext) + 1 ;
/*
* Enviando mensaje.
*/
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) {
printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length);
perror("msgsnd");
exit(1);
}
else
printf("Message: \"%s\" Sent\n", sbuf.mtext);
exit(0);
}
Ejercicio 10
Crear el siguiente programa en c, que hace referencia a un programa que escribe, llamelo message_rec.c,
compílelo
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
/*
* Declara la estructura del mensaje.
*/
main()
{
int msqid;
key_t key;
message_buf rbuf;
/*
* Consigue el id de la cola de mensje para el
* "name" 1234, el cual ha sido creado por
* el servidor.
*/
key = 1234;
/*
* Recibe una respuesta del mensaje de tipo 1.
*/
if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
perror("msgrcv");
exit(1);
}
/*
* Imprime la respuesta.
*/
printf("%s\n", rbuf.mtext);
exit(0);
}
Ejercicio 2. Utilizando una tubería simple, redireccione la salida del ejercicio resuelto 2 aun archivo de texto
simple
Ejercicio 3. En el ejercicio resuelto 5 reacomode el tamaño del buffer para mensajes de cadenas de longitud de
8 caracteres
IV. CUESTIONARIO
1. ¿Qué hace la biblioteca sys/ipc.h en los ejercicios resueltos?
2. ¿Dónde se ubica la librería types.h en su distribución Ubuntu?