消息队列概述

        消息队列是消息的链表, 存放在内存中, 由内核维护

   消息队列的特点 : 

      消息:有类型

      消息:有格式

      可实现消息的随机查询

      允许一个或多个进程向它写入或者读取消息

      从消息队列中读出消息,消息队列中对应的数据都会被删除

     每个消息队列都有消息队列标识符, 消息队列的标识符是唯一

     只有内核重启或人工删除消息队列时,该消息队列才会被删除

     

 ftok 函数

#include <sys/msg.h>

/*
 * 功能:
 *  创建一个新的或打开一个已经存在的消息队列
 *  不同的进程调用此函数,只要用相同的 key 值就能得到同一个消息队列的标识符
 * 参数:
 *  key:IPC键值
 *  msgfig:标识函数的行为及 消息队列的权限
 *    IPC_CREAT:创建消息队列
 *    IPC_EXCL:检测消息队列的存在
 *    位或权限位:消息队列位或权限位后可以设置消息队列的访问权限
 * return:
 *  成功:消息队列的标识符
 *  失败:-1
 */
int msgget(key_t key, int msgfig);

 

//shell操作
//查看消息队列
ipcs -q

//删除信息队列
ipcrm -q xxx

     

//消息队列的消息的格式
// 消息类型必须是长整型的,结构体类型的第一个成员,类型下面是消息正文,正文可以有多个成员(任意数据类型)
typedef struct _msg
{
    long mtype;    //消息类型
    char mtex[100];    //消息正文
    // ...          //消息正文有多个成员
}MSG;

发送消息

#include <sys/msg.h>

/*
 * 功能:
 *  将新消息添加到消息队列
 * 参数:
 *  msqid:消息队列的标识符
 *  msgp: 待发送消息结构体的地址
 *  msgsz: 消息正文的字节数
 *  msgfig: 函数的控制属性
 *    0:msgsnd 调用阻塞直到条件满足为止
 *    IPC_NOWAIT: 消息没有立即发送, 调用该函数的进程会立即返回
 * return:
 *  成功:0
 *  失败:-1
 */
int msgsend(int msqid, const void *msgp, size_t msgsz, int msgfig)

接收消息

#include <sys/msg.h>

/*
 *功能:
 *  从标识符为 msqid 的消息队列中接收一个消息
 *  接收消息成功,消息在消息队列中被删除
 *参数:
 *  msqid: 消息队列的标识符
 *  msgp: 消息结构体的地址
 *  msgsz:消息正文的字节数
 *  msgtyp: 消息的类型
 *    = 0:返回 第一个消息
 *    > 0: 返回 消息类型为 msgtyp 的消息
 *    < 0: 返回队列中消息类型值小于或等于 msgtyp 绝对值的消息
 *         如果这种消息有若干个,取类型值最小的消息
 *  msgflg: 函数的控制属性
 *    0: msgrcv 调用阻塞直到接收消息成功为止
 *    MSG_NOERROR: 若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节,且不通知消息发送进程
 *    IPC_NOWAIT: 调用进程会立即返回。若没有收到消息, 立即返回-1
 *return:
 *  成功:读取消息的长度
 *  失败:-1
 */
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)

消息队列的控制

 

#include <sys/msg.h>

/*
 *功能:
 *  对消息队列进行各种控制, 如修改消息队列的属性, 或删除消息消息队列
 *参数:
 *  msgid:消息队列的标识符
 *  cmd: 函数功能的控制
 *    IPC_RMID: 删除由 msqid 指示的消息队列, 将它从系统中删除并破坏相关数据结构
 *    IPC_STAT: 将 msqid 相关的数据结构中各个元素的当前值存入到由 buf 指向的结构中
 *    IPC_SET: 将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中的对应值
 *  buf: msqid_ds 数据类型的地址,用来存放或更改消息队列的属性
 *return:
 *  成功:0
 *  失败:-1
 */
int msgctl(int msqid, int cmd, struct msqid_ds *buf)

写 

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

typedef struct _msg
{
    long mtype;
    char mtext[50];
}MSG;

int main(int argc, char *argv[])
{
    key_t key;
    int msgqid;
    MSG msg;

    key = ftok(".", 2012);
    msgpid = msgget(key, IPC_CREAT | 0666);
    if(msgpid == -1)
    {
        perror("msgget");
        exit(-1);
    }
    msg.mtype = 10;
    strcpy(msg.mtext, "hello world");
    msgsnd(msgpid, &msg, sizeof(msg.mtext), 0);
    
    return 0;
}

 读

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

typedef struct _msg
{
    long mtype;
    char mtext[50];
}MSG;

int main(int argc, char *argv[])
{
    key_t key;
    int msgqid;
    MSG msg;

    key = ftok(".", 2012);
    msgpid = msgget(key, IPC_CREAT | 066);
    if(msgpid == -1)
    {
        perror("msgget");
        exit(-1);
    }

    msgrcv(msgqid, &msg, sizeof(msg.mtext), 10 , 0);
    printf("msg.mtext = %s\n", msg.mtext);
    msgctl(msgqid, IPC_RMID, NULL);
    
    return 0;
}