进程间通信——消息队列

1.消息队列原理

在这里插入图片描述
1、2…是消息类型,进程发送消息可以指定消息类型,进程接收消息也指定消息类型,这样在消息队列里识别消息类型就可以知道是不是自己需要接受的消息了。

2.消息队列示例代码

函数介绍

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/*
msgget()创建或者获取一个消息队列
msgget()成功返回消息队列 ID,失败返回-1
msqflg: IPC_CREAT
*/
int msgget(key_t key, int msqflg);


/*
msgsnd()发送一条消息,消息结构为:
struct msgbuf
{
long mtype; // 消息类型, 必须大于 0
char mtext[1]; // 消息数据
};
msgsnd()成功返回 0, 失败返回-1
msqsz: 指定 mtext 中有效数据的长度
msqflg:一般设置为 0 可以设置 IPC_NOWAIT//设置为0的话,消息队列添加满了,发送会阻塞。
*/
int msgsnd( int msqid, const void *msqp, size_t msqsz, int msqflg);

/*
msgrcv()接收一条消息
msgrcv()成功返回 mtext 中接收到的数据长度, 失败返回-1
msqtyp: 指定接收的消息类型,类型可以为 0
msqflg: 一般设置为 0 可以设置 IPC_NOWAIT//设置为0,消息队列为空或者没有这类数据的话,会阻塞。
*/
ssize_t msgrcv( int msqid, void *msgp, size_t msqsz, long msqtyp, int msqflg);


/*
msgctl()控制消息队列
msgctl()成功返回 0,失败返回-1
cmd: IPC_RMID
*/
int msgctl( int msqid, int cmd, struct msqid_ds *buf);

示例代码:wr.c进程随机发送消息类型为1、2的消息,进程 rd1.c 读取消息类型为1消息,进程rd2.c读取消息类型为 2的消息。wr.c退出的话,会先发送一条消息类型为1的数据“end”,再发送一条消息类型为 2的数据“end”,rd1和rd2分别读取,并退出,rd2.c程序里销毁消息队列 。
wr.c代码:

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

typedef struct msgdata
{
    long mtype;
    char mtest[128];
}MsgData;

int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0664);
    assert(msgid != -1);
    
    MsgData data;
    memset(&data,0,sizeof(data));
    char buff[128] = {0};
    while(1)
    {
        printf("input:\n");
        fgets(buff,128,stdin);
        buff[strlen(buff)-1] = '\0';
        strcpy(data.mtest,buff);
        if(strncmp(buff,"end",3) == 0)
        {
            data.mtype = 1;
            msgsnd(msgid, &data, 128,0);
            data.mtype = 2;
            msgsnd(msgid,&data,128,0);
            break;
        }

        data.mtype = rand()%2+1; 
        msgsnd(msgid, &data, 128, 0);
    }

    exit(0);
}

rd1.c代码:

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

typedef struct msgdata
{
    long mtype;
    char mtext[128];
}MsgData;

int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0664);
    assert(msgid != -1);
    
    MsgData data;
    memset(&data,0,sizeof(data));
    while(1)
    {
        msgrcv(msgid,&data,128,1,0);
        if(strncmp(data.mtext,"end",3) == 0)
        {
            break;
        }
        printf("data.typy:%d\n",data.mtype);
        printf("data.mtext:%s\n",data.mtext);
    }
    exit(0);
}

rd2.c代码:

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

typedef struct msgdata
{
    long mtype;
    char mtext[128];
}MsgData;

int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0664);
    assert(msgid != -1);
    
    MsgData data;
    memset(&data,0,sizeof(data));
    while(1)
    {
        msgrcv(msgid,&data,128,2,0);
        if(strncmp(data.mtext,"end",3) == 0)
        {
            break;
        }
        printf("data.typy:%d\n",data.mtype);
        printf("data.mtext:%s\n",data.mtext);
    }

    msgctl(msgid,IPC_RMID,NULL);
    exit(0);
}

运行wr.c和rd1.c、rd2.c程序。
wr.c程序发送以下图中消息:
在这里插入图片描述
rd1.c程序运行结果:
在这里插入图片描述

rd2.c程序运行结果:
在这里插入图片描述
在这里,rd2.c里面对消息队列进行了销毁。
如果没在代码里操作销毁消息队列,可以 用命令ipcrm -q + msqid进行销毁。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值