# include <sys/types.h> # include <sys/ipc.h> # include <sys/msg.h> int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg )
Valor de retorno: número de bytes da mensagem extraída da fila, ou -1 em caso de erro.
Esta função retira uma mensagem da fila. Ela recebe cinco parâmetros: o identificador da fila msqid; um ponteiro msgp para a estrutura de tipo msgbuf que contém a mensagem; um inteiro msg_sz indicando o tamanho máximo da mensgem a ser recebida; um inteiro longo msgtyp indicando o qual a mensagem a ser recebida e; um flag msgflg controlando o modo de execução da recepção da mensagem.
A função vai armazenar a mensagem lida numa estrutura apontada por msgp, a qual contém os seguintes elementos ( idênticos aos usados para o envio da mensagem):
struct msgbuf { long int mtype; /* type of received message */ char mtext[1]; /* text of the message */ };
O tamanho do campo mtext é fixado segundo as necessidades do programa (ver msgsnd() para maiores detalhes).
O parâmetro msgtyp indica qual a mensagem deve ser recebida:
Por exemplo, considerando três mensagens tendo por tipos 100, 200 e 300, a tabela a seguir indica o tipo de mensagem a ser retornada pelos diferentes valores de msgtyp:
msgtyp | tipo de mensagem retornada |
0 | 100 |
100 | 100 |
200 | 200 |
300 | 300 |
100 | 100 |
200 | 100 |
300 | 100 |
Em relação ao parâmetro msgflg:
Exemplo:
Exemplo de utilização da função msgrcv():
/* arquivo test_msgrcv.c */ #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #define KEY 123 #define MSG_SIZE_TEXT 256 /* estrutura msg associada as mensagens */ struct msgtext { long mtype ; char mtext[MSG_SIZE_TEXT] ; } msg ; int main() { int lg ; /* tamanho da mensagem recebida */ long type = 1 ; /* tipo de mensagem buscado */ int size_msg = 22 ; /* tamanho maximo do texto a ser recuperado */ int msqid ; /* identificador da fila */ char *path = "nome_de_arquivo_existente" ; /* recuperacao do identificador da fila de mensagens */ if (( msqid = msgget(ftok(path,(key_t)KEY),0)) == -1 ) { perror ("Erro msgget()") ; exit(1) ; } printf("A chave %#x esta associada a fila %d\n", ftok(path,(key_t)KEY), msqid); /* o programa vai ler na fila enquanto existirem mensagens * se as mensagens sao maiores que o tamanho maximo size_msg, * elas serao truncadas * quando a fila estiver vazia, o processo nao se bloqueia */ while((lg=msgrcv(msqid,&msg,size_msg,type,IPC_NOWAIT|MSG_NOERROR)) != -1) { printf("texto da mensagem (tamanho %d) recebido: %s\n", lg,msg.mtext) ; } perror("nao ha mais mensagens") ; exit(-1) ; }
Resultado da execução:
euler:~/> test_msgrcv A chave 0x7b045862 esta associada a fila 1152 texto da mensagem (tamanho 22) recebido: mensagem no 1 de tipo texto da mensagem (tamanho 22) recebido: mensagem no 2 de tipo ... texto da mensagem (tamanho 22) recebido: mensagem no 29 de tipo texto da mensagem (tamanho 22) recebido: mensagem no 30 de tipo nao ha mais mensagens: No message of desired type
O programa lê na fila de mensagens enquanto mensagens do tipo desejado existirem na fila. Quando a fila estiver vazia, não haverá bloqueio de processos em leitura devido ao flag IPC_NOWAIT. Por outro lado, deve-se observar que as mensagens são truncadas (flag MSG_NOERROR ao tamanho especificado para a recepção da mensagem. Além disso, ;g será igual ao tamanho da mensagem size_msg neste caso específico, uma vez que a mensagem é truncada.
Mais uma vez, pode-se constatar que a leitura (isto é a retirada) das mensagens da fila foi realmente realizada através da execução de test_msgctl.c:
euler:~/> test_msgctl A chave 0x7b045862 esta associada a fila 1152 id da fila de mensagens : 1152 id do proprietario : 1145 id do grupo do proprietario : 1000 id do criador : 1145 id do grupo do criador : 1000 direitos de acesso : 384 nb atual de bytes na fila : 0 nb de mensagens na fila : 0 nb maximal de bytes na fila : 16384 pid do ultimo escritor : 2192 pid do ultimo leitor : 2194 data da ultima escrita : Tue Oct 17 06:53:54 2000 data da ultima leitura : Tue Oct 17 06:57:17 2000 data da ultima modificacao : Tue Oct 17 06:43:09 2000
Note que o número de mensagens na fila agora vale 0 e que a data da última escrita na fila é idêntica àquela obtida na execução precedente de test_msgctl.