消息队列通信相关API简述

原文链接:进程间通信(IPC)介绍_tangtang_yue的博客-CSDN博客_进程间通信(ipc)介绍

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

1.特点

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

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

  3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

2.相关API

1 #include <sys/msg.h>
2 // 创建或打开消息队列:成功返回队列ID,失败返回-1
3 int msgget(key_t key, int flag);
4 // 添加消息:成功返回0,失败返回-1
5 int msgsnd(int msqid, const void *ptr, size_t size, int flag);
6 // 读取消息:成功返回消息数据的长度,失败返回-1
7 int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
8 // 控制消息队列:成功返回0,失败返回-1
9 int msgctl(int msqid, int cmd, struct msqid_ds *buf);

①创建获取消息队列并且接收消息数据:

#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(int argc, char *argv[])
{
        int msgId;
        struct msgbuf readBuf;

        msgId = msgget(0x1234, IPC_CREAT | 0777);    //获取创建消息队列,IPC_CREAT后记得加上权限
        if (msgId == -1){
                printf("get queue failuer!\n");
        }

        msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0);   //0代表进程会一直阻塞直到获取到消息队列信息
        printf("read: %s\n", readBuf.mtext);

        return 0;
}

创建获取消息队列并且发送消息数据:

#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(int argc, char *argv[])
{
        int msgId;
        struct msgbuf sendBuf = {888, "this is message from queue"};

        msgId = msgget(0x1234, IPC_CREAT | 0777);    //获取创建消息队列,IPC_CREAT后记得加上权限
        if (msgId == -1){
                printf("get queue failuer!\n");
        }

        msgsnd(msgId, &sendBuf, sizeof(sendBuf.mtext), 0);
        printf("send over!\n");

        return 0;
}

③运行结果:

 ④接收端实现两个进程相互接发数据内容:

#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(int argc, char *argv[])
{
        int msgId;
        struct msgbuf readBuf;
        struct msgbuf sendBuf = {988, "thanks for your sending message"};

        //key_t ftok(const char *pathname, int proj_id);
        key_t key;
        key = ftok(".", 24);   //"."代表当前路径,int id一般为8位1-255
        printf("key = %x\n", key);

        msgId = msgget(key, IPC_CREAT | 0777);    //获取创建消息队列,IPC_CREAT后记得加上权限
        if (msgId == -1){
                printf("get queue failuer!\n");
        }

        msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0);   //0代表进程会一直阻塞直到获取到消息队列信息
        printf("read from queue: %s\n", readBuf.mtext);

        msgsnd(msgId, &sendBuf, sizeof(sendBuf.mtext), 0);
        printf("send successfully!\n");

        //int msgctl(int msqid, int cmd, struct msqid_ds *buf);
        msgctl(msgId, IPC_RMID, NULL);  //为了避免创建获取的消息队列无效堆积,IPC_RIMD参数可以在进程终止后干掉先前的消息队列

        return 0;
}

⑤发送端实现两个进程相互接发数据内容:

#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(int argc, char *argv[])
{
        int msgId;
        struct msgbuf readBuf;
        struct msgbuf sendBuf = {888, "this is message from queue"};

        //key_t ftok(const char *pathname, int proj_id);
        key_t key;
        key = ftok(".", 24);
        printf("key = %x\n", key);

        msgId = msgget(key, IPC_CREAT | 0777);    //获取创建消息队列,IPC_CREAT后记得加上权限
        if (msgId == -1){
                printf("get queue failuer!\n");
        }

        msgsnd(msgId, &sendBuf, sizeof(sendBuf.mtext), 0);
        printf("send over!\n");

        msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 988, 0);
        printf("read from queue: %s\n", readBuf.mtext);

        //int msgctl(int msqid, int cmd, struct msqid_ds *buf);
        msgctl(msgId, IPC_RMID, NULL);  //通过msgctl函数控制消息队列,IPC_RMID参数将消息队列干掉,第三个参数一般为NULL

        return 0;
}

⑥运行结果:

 PS:在获取创建消息队列时,消息队列ID既可以手动输入十六进制数给定,也可以通过ftok()函数自动获取,其相关介绍如下:

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。

另外msgctl()用法:int msgctl(int msqid, int cmd, struct msqid_ds *buf)

msgctl(msgId, IPC_RMID, NULL)。为了避免创建获取的消息队列无效堆积,IPC_RIMD参数可以在进程终止后干掉先前的消息队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值