unix 讯息队列实例

unix 消息队列实例

本文来自:http://blog.sina.com.cn/s/blog_413fbf500100vyyj.html
unix系统中进程可以通过消息进行通信,消息是格式化的可变长度的信息单元,包含消息类型、数据长度及数据三部分内容。每个消息都有一个唯一的名称key,同时还有一个唯一的消息队列描述符。
    消息队列的使用:
1、建立:
    调用: int msgget(int key,int flags);
    key为消息队列名称,flags为用户设置标志,一般设置消息队列的访问权限等,权限取值如下:
                            权限                  八进制整数
                          用户可写                  0400
                          用户可读                  0200
                          同组可写                  0040
                          同组可读                  0020
                          其它可写                  0004
                          用户可读                  0002
    权限值可加和组合,如 msgget(0x888,0660|IPC_CREAT) 表示创建队列名称为0x888,用户和同组可读写的消息队列,返回队列描述符,如果该消息队列已存在则返回对应的消息队列描述符。

2、发送: 
    调用:  int msgsnd(int msgid,(void*)&mymsg,int msgsz,int msgflg)
    msgid为msgget返回的消息队列描述符,mymsg是指向发送消息的结构,结构需要定义,格式如:
                struct mymsg{
                long mytype;   //消息类型
                char msgtext[];  //消息内容
               }
    msgsz是消息内容msgtext的长度,msgflg是消息设置,一般指定无内存存储消息时进程等待还是返回。
    函数成功返回0 失败返回 -1

3、接收:
   调用   int msgrcv(int msgid,(void*)&mymsg,int msgsz,int msgtyp,int msgflg)  
   msgid、mymsg、msgsz、msgflg都与msgsnd的一致,msgtyp指定用户读取消息的类型,如:
                  (1) msgtyp=0,返回Unix消息队列中的第一个消息
                  (2) msgtyp>0,返回Unix消息队列中类型为msgtyp的第一个消息
                  (3) msgtyp<0,返回Unix消息队列中小于等于msgtyp绝对值的最低类型的第一个消息
   函数成功返回0 失败返回 -1。

4、消息队列的控制:
   调用:   int msgctl(int msgid,int cmd,(struct msgid_ds *)&buf)
   msgid是要操作的队列描述符,cmd是操作类型,如:
               IPC_STAT 查看消息队列的状态,结果放入buf指向的结构
               IPC_RMID 删除指定的msgid及其相关的队列和结构
               IPC_SET 为指定的msgid设置属主标识、同组标识、操作权、最大字节数等
5、自测实例:
   //发送方,读取输入,发送到key为0x1234的消息队列中
       msgc.c:
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <sys/errno.h>

struct mymsg
{
    long mtype;
    char ctx[128];
};

int main(void)
{
    struct mymsg mybuf;
    int msgid;
    int rc = 0;
   
    msgid = msgget(0x1234,0666 | IPC_CREAT);
   
    if(msgid < 0)
    {
        fprintf(stderr,"open msg %x fail\n",0x1234);
        exit(1);
    }
    memset(&mybuf,0,sizeof(mybuf));
    mybuf.mtype = getpid();
   
    printf("Please input your message: \n");
   
    fgets(mybuf.ctx,sizeof(mybuf.ctx),stdin);
    rc = msgsnd(msgid,(void*)&mybuf,strlen(mybuf.ctx),IPC_NOWAIT);
   
    if(rc < 0)
    {
        printf("Send message error,errno: %d\n",errno);
        return (rc);
    }else
    {
        printf("Send message success.\n");
    }
    return 0;
}
  
//读取方,从0x1234中读取第一条消息并输出  
    msgs.c:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>

struct mymsg
{
    long mtype;
    char ctx[128];
};

int main(void)
{
    struct mymsg buf;
    int msgid;
    int rc = 0;
    msgid = msgget(0x1234,0666|IPC_CREAT);
   
    if(msgid <0)
    {
        fprintf(stderr,"Open msg %x failed.errno: \n",0x1234,errno);
        exit(1);
    }
   
    memset(&buf,0,sizeof(buf));
    rc = msgrcv(msgid,(void*)&buf,sizeof(buf.ctx),0,IPC_NOWAIT);
   
    if(rc < 0)
    {
        fprintf(stderr,"Receive msg %x failed.errno: \n",0x1234,errno);
        exit(1);
    }
   
    fprintf(stderr,"Get the message : pid: %d,len:%d,message: %s.\n",buf.mtype,rc,buf.ctx);
    return 0;
}

make编译后执行结果:
# ./tmsgc
Please input your message:
hello this is the test message!
Send message success.

# ./tmsgs
Get the message : pid: 925830,len:32,message: hello this is the test message!
.
# ipcs -q    //查看ipc
T        ID     KEY        MODE       OWNER    GROUP
q 186646559 0x00001234 --rw-rw-rw-       rk   db2grp