上文將消息隊列中放入了數據,其他進程就可以從中讀取消息了。讀取消息的函數是msgrcv(),該函數原型爲:
#include <sys/msg.h>
int msgrcv(int msgid, struct msgbuf *msgp, size_t msgsz, long int msgtyp, int msgflg);
相關參數的含義上文已經說明,此處略過。
使用相同的參數PATH_NAME和PROJ_ID來調用ftok()函數,發現在不同的進程中調用它生成的msgkey並不一致。這導致從消息隊列裏讀取消息失敗。兩次在不同進程中使用相同的參數調用ftok函數,生成的msgkey的情況,參看下圖:
那麼現在必須修改代碼,在讀取消息的進程中,必須顯示地指明寫入消息時用到的msgkey。否則讀取消息失敗。以下代碼,將msgkey硬編碼進了msgget函數中:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define BUF_SIZE 256
#define PROJ_ID 32
#define PATH_NAME "."
int main(void)
{
/*用戶自定義消息緩衝區*/
struct mymsgbuf{
long msgtype;
char ctrlstring[BUF_SIZE];
} msgbuffer;
int qid; /*消息隊列標識符*/
int msglen;
key_t msgkey;
/*獲取鍵值*/
if((msgkey = ftok(PATH_NAME, PROJ_ID)) == -1)
{
perror("ftok error!\n");
exit(1);
}else{
printf("msgkey = %d\n",msgkey);
}
/*獲取消息隊列標識符*/
//if((qid = msgget(msgkey, IPC_CREAT|0660)) == -1)
if((qid = msgget(3739636, IPC_CREAT|0660)) == -1) //此處將寫入消息時的msgkey值硬編碼到msgget函數中
{
perror ("msgget error!\n");
exit (1);
}
msglen = sizeof(struct mymsgbuf) - 4;
if (msgrcv(qid, &msgbuffer, msglen, 3, 0) == -1) /*讀取數據*/
{
perror ("msgrcv error!\n");
exit (1);
}
printf("Get message %s\n", msgbuffer.ctrlstring);
exit(0);
}
現在的運行結果: