UNIX环境下的消息队列

Posted on 2015-06-04 11:46  Bumble_Bee  阅读(774)  评论(0编辑  收藏  举报

  消息队列和共享内存一样,也是一种IPC对象。消息队列其实就是消息的链表,每一则消息都是用户自己的结构体。服务端这边创建消息队列,客户端这边打开消息队列,两个进程就可以进行通信。创建和打开消息队列使用函数msgget,发送消息到消息队列使用函数msgsnd,从消息队列中取出消息使用函数msgrcv,通信完毕后删除消息队列使用函数msgctl。这四个函数就是消息队列通信编程主要用到的函数,man命令就可以看到他们的详细信息。

  前面说到消息是用户自己构造的结构体,其实这个结构体也是有讲究的,这是linux给出的原型

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };

  第一个是整形数字,标识消息的类型,可由用户自己定义。第二个就是消息的内容。其他部分可由用户自己添加。下面直接贴代码吧,感觉代码比文字更直观。我这里只是扫盲式的学了一下,接收消息的时候比较简单粗暴,直接接受了当前队列的第一则消息,没有设置其他的标志。

/*send.c*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>


struct msgt
{
/*消息类型*/
int msgtype;
char student_num[20];
char name[20];
};


int main(int argc, char const *argv[])
{
int msgid;
int running = 1;
int msg_type;
char number[20];
char str[20];


struct msgt* msgs = (struct msgt*) malloc( sizeof(struct msgt));


/*构造键值*/
key_t key = ftok(".", 4);


/*创建消息队列*/
msgid = msgget(key, IPC_CREAT|0666);
printf("msgid is %d\n", msgid);


/*循环*/
while(running)
{
printf("please input message type, 0 for quit\n");
/*从键盘中读入消息类型和数据*/
scanf("%d", &msg_type);
if(msg_type == 0)
{
running = 0;
msgs->msgtype = msg_type;
msgsnd(msgid, (const void *)msgs, sizeof(struct msgt), 0);
break;
}
printf("please input your student number\n");
scanf("%s", &number);



printf("please input your name\n");
scanf("%s", str);
/*将消息发送到消息队列*/
msgs->msgtype = msg_type;
strcpy(msgs->student_num, number);
strcpy(msgs->name, str);
msgsnd(msgid, (const void *)msgs, sizeof(struct msgt), 0);


}


/*删除消息队列*/
msgctl(msgid, IPC_RMID, 0);


free((void *) msgs);


return 0;
}

 
/*recieve.c*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>


struct msgt
{
/*消息类型*/
int msgtype;
char student_num[20];
char name[20];
};


int main(int argc, char const *argv[])
{

int i;
int size;
int msgid;

struct msgt* msgs = (struct msgt*) malloc( sizeof(struct msgt));


/*构造键值*/
key_t key = ftok(".", 4);


/*打开消息队列*/
msgid = msgget(key, IPC_EXCL);


printf("msgid is %d\n", msgid);


while(1)
{
size = msgrcv(msgid, msgs, sizeof(struct msgt), 0, 0);
if(size == -1)
return;
printf("your student number is %s\nyour name is %s\nsize is %d\n", msgs->student_num, msgs->name, size);


}
free((void *) msgs);


return 0;
}

 

  这里说点写这个程序出现的问题,一开始定义消息结构体的时候我是这么干的

struct msgt* msgs;

  正常运行发送和接收都还好,但是当send输入0退出程序时就出现段错误了,最后用core dump定位才发现定义结构体指针没有初始化,就这破问题调了好久,血淋淋的教训。以后再敲代码的时候一定要记住,结构体指针需要malloc初始化!!!嗯!

  如果有错误或者疑问,欢迎指出!