消息队列

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

1、特点

1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。

2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。

3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
如何创建一个新的消息队列
1.B程序如何加消息队列
2.A程序如何从队列拿到消息

A B 使用同一个队列通信

消息队列不同的消息可以在监听中判断 消息队列key_消息队列

 

程序A                       程序B
1.获取队列                  1.获取/创建
2.读                        2.写数据到队列

2、原型

1 #include <sys/msg.h>
2 // 创建或打开消息队列:成功返回队列ID,失败返回-1
3 int msgget(key_t key, int flag);//key是索引值   flag打开队列方式
4 // 添加消息:成功返回0,失败返回-1
5 int msgsnd(int msqid, const void *ptr, size_t size, int flag);// msqid队列的id,ptr是消息, size 大小 ,flag 标志位
6 // 读取消息:成功返回消息数据的长度,失败返回-1
7 int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);//type 队列的类型
8 // 控制消息队列:成功返回0,失败返回-1
9 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
在以下两种情况下,msgget将创建一个新的消息队列:

如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。
key参数为IPC_PRIVATE。
函数msgrcv在读取消息队列时,type参数有下面几种情况:

type == 0,返回队列中的第一个消息;
type > 0,返回队列中消息类型为 type 的第一个消息;
type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。
可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。
Msg_Gettest1.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
//       int msgget(key_t key, int msgflg);
//       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
struct msgbuf
{
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};
int main()
{
//      1.huoqu
        struct msgbuf readBuf;

        int msgId = msgget(0x1234,IPC_CREAT|0777);//can read can write can zhixing
        if(msgId == -1){
                printf("get que failed\n");
        }
        msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);
        printf("read from que:%s\n",readBuf.mtext);
        return 0;
}
Msg_Sendtest1.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
//       int msgget(key_t key, int msgflg);
//       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
struct msgbuf
{
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};
int main()
{
//      1.huoqu
        struct msgbuf sendBuf = {888,"this is message from queue!"};
        int msgId = msgget(0x1234,IPC_CREAT|0777);//can read can write can zhixing
        if(msgId == -1){
                printf("get que failed\n");
        }
        msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
        return 0;
}

 运行结果为:

消息队列不同的消息可以在监听中判断 消息队列key_队列_02

消息队列不同的消息可以在监听中判断 消息队列key_队列_03

=============================================================================================================================================================

Msg_send+getdemo2.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
//       int msgget(key_t key, int msgflg);
//       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
struct msgbuf
{
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};
int main()

//      1.huoqu
        struct msgbuf sendBuf = {888,"this is message from queue!"};
        struct msgbuf readBuf;
        int msgId = msgget(0x1235,IPC_CREAT|0777);//can read can write can zhixing
        if(msgId == -1){
                printf("get que failed\n");
        }
        msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
        printf("send over\n");
        msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),988,0);
        printf("return from rcv:%s\n",readBuf.mtext);
        return 0;
}
Msg_get+senddemo2.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
//       int msgget(key_t key, int msgflg);
//       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
struct msgbuf
{
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};
int main()
{
//      1.huoqu
        struct msgbuf readBuf;
        int msgId = msgget(0x1235,IPC_CREAT|0777);//can read can write can zhixing
        if(msgId == -1){
                printf("get que failed\n");
        }
        msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);
        printf("read from que:%s\n",readBuf.mtext);
        struct msgbuf sendBuf = {988,"this is message from queue!"};
        msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
        return 0;
}

运行结果为:

消息队列不同的消息可以在监听中判断 消息队列key_消息队列_04

消息队列不同的消息可以在监听中判断 消息队列key_队列_05

=============================================================================================================================================================

key值生成及消息队列的移除

系统建立IPC通讯 (消息队列信号量共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

头文件
#include <sys/types.h>
#include <sys/ipc.h>
函数原型:
key_t ftok( const char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。虽然是int类型,但是只使用8bits(1-255)。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i

去增加ftok函数的使用 

消息队列不同的消息可以在监听中判断 消息队列key_消息队列_06

消息队列不同的消息可以在监听中判断 消息队列key_linux_07

 

消息队列不同的消息可以在监听中判断 消息队列key_#include_08

消息队列不同的消息可以在监听中判断 消息队列key_消息队列_09

 消息队列的移除

使用msgctl函数 

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

去man msgctl 查找cmd

消息队列不同的消息可以在监听中判断 消息队列key_消息队列_10

   一直使用RMID  移除ID