linux消息队列

消息队列:
基本特点:是由内核负责维护管理的链式数据队列,不是根据先后顺序出队,而是根据消息类型进行收发数据
int msgget(key_t key, int msgflg);
功能:创建\获取消息队列
key:IPC键值
msgflg:
IPC_CREAT 消息队列已存在则获取,否则创建
IPC_EXCL 消息队列已存在则返回错误
注意:如果创建需要提供权限
返回值:IPC标识符,失败-1

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    功能:向消息队列发送消息包
    msqid:IPC标识符
    msgp:要发送的消息包的首地址
        struct msgbuf {
           long mtype;      //  消息类型
           char mtext[n];   //  数据
           ...
       };
    msgsz:数据的字节数,不包含消息类型
    msgflg:
        阻塞发送一般给0
        IPC_NOWAIT 当消息队列满,不等待立即返回
    返回值:成功返回0,失败返回-1

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
    功能:从消息队列中接收对应消息包的数据
    msqid:IPC标识符
    msgp:存储消息包的内存首地址
    msgsz:存储数据的内存字节数(尽量大些)
    msgtyp:消息类型(按照类型获取,不按照顺序)
        >0 读取消息类型=msgtyp的消息
        =0 读取消息队列中第一条消息
        <0 读取消息类型小于abs(msgtyp)的消息,如果有多个则读值最小的
    msgflg
        IPC_NOWAIT 消息队列都不符合时不阻塞,立即返回
        MSG_EXCEPT 如果msgtyp>0,则读取第一条不等于msgtyp的消息
        MSG_NOERROR 如果不包含此标志,如果实际发送过来的数据字节数>接收的字节数,则返回失败,如果包含此标志,那么就只读取接收的字节数,一定会成功
    返回值:成功读取到数据的字节数

int msgctl(int msqid,int cmd,struct msqid_ds *buf);
功能:获取\修改消息队列的属性、删除队列
msqid:IPC标识符
cmd:
    IPC_STAT   获取消息队列属性 buf输出型参数
    IPC_SET    设置消息队列属性 buf输入型参数
    IPC_RMID   删除消息队列     NULL
buf

编程模型:
    进程A                   进程B
  创建消息队列             获取消息队列
  发送消息                  获取消息
  获取消息                  发送消息
  删除消息队列

1.先定义一个message.h存放结构体
使用头文件卫士

#pragma once
#define MAXMSG 256
typedef struct msgbuf
{
	long type;
	char data[MAXMSG];	

}Msg;


2.进程A
message.c

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

#include "message.h"
int main(int argc,const char* argv[])
{
	//创建消息队列
	int msgid=msgget(ftok(".",120),  IPC_CREAT|0644 );
	if(msgid<0)
	{
		perror("msgget");
	return -1;
	}

	Msg msg={};
	for(;;)
	{
	msg.type=5;
	printf(">>>>>");
	scanf("%s",msg.data);
	//发送
	if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
	{
		perror("msgsnd");
		return -1;
	}
	if(0==strcmp("quit",msg.data)) break;//输入quit主动结束
	//接受数据
	if(0==msgrcv(msgid,&msg,MAXMSG,6,0))
	{
		perror("msgrcv");
		break;
	}
	printf("recv:%s\n",msg.data);
	if(0==strcmp("quit",msg.data)) break;

	}
	printf("通信结束\n");
	sleep(1);
	//删除消息队列
	if(msgctl(msgid,IPC_RMID,NULL))
	{
		perror("msgctl");

	}

	return 0;
}

3.进程B
messageB.c

#include <stdio.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include"message.h"
int main(int argc,const char* argv[])

{

	//创建消息队列
	int msgid=msgget(ftok(".",120),  0);
	if(msgid<0)
	{
		perror("msgget");
		return -1;
	}
	Msg msg={};
	for(;;)
	{
	//接受数据
	if(0==msgrcv(msgid,&msg,MAXMSG,5,0))
	{
		perror("msgrcv");
		break;
	}
	printf("recv:%s\n",msg.data);
	if(0==strcmp("quit",msg.data)) break;//被动结束
	msg.type=6;
	printf(">>>");
	scanf("%s",msg.data);
	//发送
	if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
	{
		perror("msgsnd");
		return -1;
	}

	if(0==strcmp("quit",msg.data)) break}
	printf("通信结束\n");
	sleep(1);
	/*//删除消息队列
	if(msgctl(msgid,IPC_RMID,NULL))
	{
		perror("msgctl");

	}*/
	return 0;
}

主动结束,被动结束
测试结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值