进程间通信——信息队列

参考来源:(1条消息) 【转】进程间的五种通信方式_进程间的5种通信方式_哈市雪花的博客-CSDN博客icon-default.png?t=N176https://blog.csdn.net/baidu_38621657/article/details/105724822?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167860274416800222885633%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167860274416800222885633&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-105724822-null-null.142^v73^control,201^v4^add_ask,239^v2^insert_chatgpt&utm_term=%E8%BF%9B%E7%A8%8B%E9%97%B4%E7%9A%84%E4%BA%94%E7%A7%8D%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F&spm=1018.2226.3001.4187

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

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

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

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

2、原型

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);

在以下两种情况下,msgget将创建一个新的消息队列:

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

type == 0,返回队列中的第一个消息;
type > 0,返回队列中消息类型为 type 的第一个消息;
type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。
可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。(其他的参数解释,请自行Google之)

3、例子
下面写了一个简单的使用消息队列进行IPC的例子,服务端程序一直在等待特定类型的消息,当收到该类型的消息以后,发送另一种特定类型的消息作为反馈,客户端读取该反馈并打印出来。

DuiLie_get.c

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

struct msgbuf
{
        long mtype;
        char mtext[128];
};

int main()
{
        struct msgbuf readBuf;
        key_t key;
        key = ftok(".",'z');
        printf("key =  %x\n",key);


        int msgId = msgget(key,IPC_CREAT|0777);
        if(msgId==-1){

                printf("get que failuer\n");
        }

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

        struct msgbuf sendBuf = {988,"thank you for reach"};
        msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);

        msgctl(msgId,IPC_RMID,NULL);

        return 0;
}

DuiLie_send.c

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

struct msgbuf
{
        long mtype;
        char mtext[128];
};

int main()
{
        struct msgbuf sendBuf = {888,"this is message quen"};
        struct msgbuf readBuf;

        key_t key;
        key = ftok(".",'z');
        printf("key =  %x\n",key);


        int msgId = msgget(key,IPC_CREAT|0777);
        if(msgId==-1){

                printf("get que failuer\n");
        }

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

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

        msgctl(msgId,IPC_RMID,NULL);

        return 0;
}

两终端运行情况:

 key的获取:
ftok 系统IPC键值的格式转换函数

系统建立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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值