troca de mensagens - IME – Instituto de Matemática e Estatística

Transcrição

troca de mensagens - IME – Instituto de Matemática e Estatística
Página 1 de 5
INSTITUTO SUPERIOR DE CIÊNCIAS DO TRABALHO E DA EMPRESA
Sistemas Operativos
2º Semestre
2003/2004
ETI - IGE
Aula 04
Filas de mensagem
1. Criar uma fila de mensagens. Mandar uma mensagem.
Os procedimentos para filas de mensagens são em parte semelhantes aos dos semáforos. Para criar uma fila de mensagens usase a função msgget, como se exemplifica no seguinte programa que também envia uma mensagem para a fila criada.
Para enviar uma mensagem usa-se a função msgsnd. O primeiro argumento é, obviamente, o id obtido de msgget. O segundo
argumento é a mensagem propriamente dita, o terceiro argumento é o tamanho da mensagem e o último argumento é,
normalmente, 0 (mas adiante veremos outras hipóteses).
Sobre a mensagem, a regra é que deve existir um campo int (designado de "tipo" da mensagem) antes da mensagem
propriamente dita. Dentro desta regra, é o programa que define a estrutura das mensagens. Neste caso foi definida uma
estrutura MsgStruct que prevê mensagens contendo, no máximo, 250 caracteres.
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct
{
int type;
char text[250];
} MsgStruct;
main()
{
int msg_id;
int status;
MsgStruct msg;
// ligar à fila de mensagens
msg_id = msgget ( 1000, 0600 | IPC_CREAT );
exit_on_error (msg_id, "Criação/Ligação");
// enviar ums mensagem
msg.type = 1;
strcpy( msg.text, "Uma mensagem qualquer.");
status = msgsnd( msg_id, &msg, sizeof(msg.text), 0);
exit_on_error (msg_id, "Envio");
printf ("Mensagem enviada!\n");
}
2. Comandos
O comando ipcs -m (ou só ipcs) permite ver as filas de mensagens criadas. Pode também, nessa lista, ver o número de
mensagens actualmente em espera na fila.
3. Receber uma mensagem.
O seguinte programa recebe (receber, neste contexto, quer dizer retirar) uma mensagem da fila. A única diferença sensível é que,
file://C:\DOCUME~1\THIAGO~1\CONFIG~1\Temp\VOM29K58.htm
5/9/2005
Página 2 de 5
em vez de msgsnd para mandar uma mensagem, temos a função msgrcv para receber.
Nesta chamada o primeiro, segundo e terceiro argumentos têm significados idênticos ao de mandar. O segundo indica a estrutura
que vai receber a mensagem e o terceiro indica a dimensão dessa estrutura.
O quarto argumento indica o tipo de mensagem que se pretende receber. O programa só vai receber mensagens do tipo
indicado, neste caso do tipo 1 (ou seja, se houver na fila mensagens de outro tipo, para este efeito, é como se não existissem).
Felizmente que o programa anterior mandou a mensagem como sendo do tipo 1!
Finalmente, o último argumento continua em 0. Isto faz com que, se não houver uma mensagem disponível na fila (que seja do
tipo 1) o programa ficará bloqueado em espera; só desbloqueará quando alguém enviar uma nova mensagem (do tipo 1) para a
fila.
#include
#include
#include
#include
<stdio.h>
<sys/ipc.h>
<sys/msg.h>
"my_include.h"
typedef struct
{
int type;
char text[250];
} MsgStruct;
main()
{
int msg_id;
int status;
MsgStruct msg;
// ligar à fila de mensagens
msg_id = msgget ( 1000, 0600 | IPC_CREAT );
exit_on_error (msg_id, "Criação/Ligação");
// receber uma mensagem (bloqueia se não houver)
status = msgrcv( msg_id, &msg, sizeof(msg.text), 1, 0);
exit_on_error (msg_id, "Recepção");
printf ("MENSAGEM <%s>\n", msg.text);
}
4. No wait
Experimente os programas anteriores com diferentes sequências; por ex: com o primeiro põe várias mensagens na fila; com o
segundo tirar cada um delas. Evidentemente, o segundo programa só bloqueia se, no momento, não houver qualquer mensagem
disponível.
Em alternativa, o último argumento do msgrcv pode ser IPC_NOWAIT. Neste caso o msgrcv não bloqueia. Vai buscar uma
mensagem e se houver recolhe senão segue à sua vida.
5. Exemplo: cliente / servidor
O exemplo seguinte implementa um modelo em que um ou mais clientes mandam mensagens para um servidor, que responde a
cada um deles.
A estrutura da mensagem é agora maios elaborada. Além da parte obrigatória (ou seja, o "tipo" da mensagem) a mensagem tem
agora dois campos: um identificador que irá conter o número do processo que envia a mensagem e o texto da mensagem,
propriamente dito.
O esquema é o seguinte:
file://C:\DOCUME~1\THIAGO~1\CONFIG~1\Temp\VOM29K58.htm
5/9/2005
Página 3 de 5
-
o servidor só procura na fila mensagens do tipo 1;
o cliente manda para o servidor uma mensagem do tipo 1, indicando o seu pid no corpo da mensagem;
o servidor responde com uma mensagem com tipo igual ao pid indicado pelo cliente;
em conformidade, o cliente, procura na fila de mensagens uma resposta com tipo igual ao seu próprio pid;
file://C:\DOCUME~1\THIAGO~1\CONFIG~1\Temp\VOM29K58.htm
5/9/2005
Página 4 de 5
SERVIDOR
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct
{
int type;
struct _msg_struct
{
int pid;
char text[250];
} msg;
} MsgStruct;
main()
{
int msg_id;
int status;
MsgStruct msg;
int premio = 0;
// ligar à fila de mensagens
msg_id = msgget ( 1000, 0600 | IPC_CREAT );
exit_on_error (msg_id, "Criação/Ligação");
// receber uma mensagem (bloqueia se não houver)
while (1 )
{
status = msgrcv( msg_id, &msg, sizeof(msg.msg), 1, 0);
exit_on_error (msg_id, "Recepção");
printf ("DE PID %d: <%s>\n", msg.msg.pid, msg.msg.text);
msg.type = msg.msg.pid;
if ( ++premio %5 == 0 )
{
strcpy ( msg.msg.text, "PREMIO!" );
printf ("Premio para PID =%d\n", msg.msg.pid);
}
else
strcpy ( msg.msg.text, "Tente de novo." );
status = msgsnd( msg_id, &msg, sizeof(msg.msg), 0);
exit_on_error (msg_id, "Resposta");
}
}
file://C:\DOCUME~1\THIAGO~1\CONFIG~1\Temp\VOM29K58.htm
5/9/2005
Página 5 de 5
CLIENTE
#include
#include
#include
#include
<stdio.h>
<sys/ipc.h>
<sys/msg.h>
"my_include.h"
typedef struct
{
int type;
struct _msg_struct
{
int pid;
char text[250];
} msg;
} MsgStruct;
main()
{
int msg_id;
int status;
MsgStruct msg;
char s[250];
// ligar à fila de mensagens
msg_id = msgget ( 1000, 0600 | IPC_CREAT );
exit_on_error (msg_id, "Criação/Ligação");
printf ("PID=%d\n", getpid());
while ( 1 )
{
msg.type = 1;
msg.msg.pid = getpid();
printf("Mensagem: ");
gets(s);
strcpy( msg.msg.text, s );
status = msgsnd( msg_id, &msg, sizeof(msg.msg), 0);
exit_on_error (msg_id, "Envio");
status = msgrcv( msg_id, &msg, sizeof(msg.msg), getpid(), 0);
exit_on_error (msg_id, "Resposta");
printf ("Resposta: %s\n", msg.msg.text );
}
}
file://C:\DOCUME~1\THIAGO~1\CONFIG~1\Temp\VOM29K58.htm
5/9/2005

Documentos relacionados