IPC之消息队列(msget函数、msgsnd函数、msgrcv函数)及其代码示例——linux系统编程

linux 专栏收录该内容
17 篇文章 0 订阅

消息队列介绍

消息队列:IPC之一
内核开辟的一个队列,进程可以通过调用系统API方式调用消息队列函数,给内核消息队列发送或者接收数据

涉及函数:
包含头文件:<sys/msg.h><sys/types.h>和<sys/ipc.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgget(key_t key, int msgflg);
msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msg_typ, int msgflg);
msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);

ipcs命令可以查看消息队列,也可以查看共享内存。进程结束消息队列还存在,说明消息队列是由内核维护的
下文中1:代表参数一的解释

msgget:创建和访问一个消息队列

msgget用来创建和访问一个消息队列
int msgget(key_t key, int msgflg);

1:key_t用户指定的要创建的消息队列的名字(一般为整形数字)
2:msgflg权限位:0644,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:
如果操作成功,msgget将返回一个非负整数,即该消息队列的标识码;如果失败,则返回“-1”
例子:

msg_id = msgget((key_t)1122, IPC_CREAT | 0666);

msgsnd:发送信息,把一条消息添加到消息队列里去

msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);

1:由msgget函数返回的消息队列标识码
2:是指针,指针指向准备发送的消息的结构体
发送消息struct msgbuf的标准:
The msgp argument is a pointer to a caller-defined structure of the
following general form:

       struct msgbuf {
           long mtype;       /* message type, must be > 0 */
           char mtext[1];    /* message data */
       };

3:msg_sz发送结构体中除long int 的大小,也就是struct msgbuf中的char mtext的大小
4:控制着当前消息队列满或到达系统上限时将要发生的事情
msgflg=IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。

返回值:返回“0”,如果失败,则返回“-1”
例子:

if(msgsnd(msg_id,&msginfo,sizeof(msginfo.message),0)==-1)
{
	perror("message send error:");
}

msgrcv:从一个消息队列里检索(接收)消息

msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msg_typ, int msgflg);
1:msgid: 由msgget函数返回的消息队列标识码
2:msg_ptr:是一个指针,指针指向准备接收的消息,
3:msg_sz发送结构体中除long int 的大小,也就是struct msgbuf中的char mtext的大小
4:msgtype:它可以实现接收优先级的简单形式
一个消息队列可以被很多进程共享,也就是多个进程都可能使用这个消息队列,那么消息如何进行区分?——mtype
mtype用来区别不同消息通常是,发送和接收的mtype数字一一对应才可以收到,当mtype==0:接收所有消息
如果mtype的值在消息队列中没有对应值且不为0,则接收将堵塞

• msgtype=0返回队列第一条信息
• msgtype>0返回队列第一条类型等于msgtype的消息 
• msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息
5:msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事
• msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
• msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
• msgtype>0且msgflg=MSC_EXCEPT,接收类型不等于msgtype的第一条消息。

返回值:成功返回实际放到接收缓冲区里去的字符个数returns the number of bytes actually copied into the
mtext array.如果失败,则返回“-1”
例子:

if (msgrcv(msg_id, &msginfo, sizeof(msginfo.message), 5, IPC_NOWAIT) == -1)//msgrcv接收,mtype和发送的mtype不一样也可以收到
{
	perror("message recv error:");
	return -1;
}

注意:
1.当重复往消息队列里面发送相同时间的时候,消息是不会被阻塞的,每一次发送都有效且相互独立
2.如果消息队列里面没有数据了,再接收也将阻塞,若不想阻塞,可设置msgflg=IPC_NOWAIT,将立刻返回并产生错误
IPC_NOWAIT
Return immediately if no message of the requested type is in the queue. The system call fails with errno set to ENOMSG.

3.最多可以创建256个消息队列
4.发送的每个消息的最大长度是8192字节
5.一个消息队列接收所有消息的最大容量是16384字节,16384/8192==2

代码实例

消息队列发送端:


#include <iostream>
#include<unistd.h>//unix stand lib
#include<sys/types.h>
#include<sys/fcntl.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<dirent.h>//file dir
#include <sys/wait.h>//wait func
#include <stdlib.h>//ststem
#include <signal.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;


typedef struct
{
	long mtype;
	char message[50];
}MSG_DATA;


//====================================queue
int main(int argc, char *argv[])
{
	int msg_id;
	msg_id = msgget((key_t)1122, IPC_CREAT | 0666);
	if (msg_id == -1)
	{
		perror("msgget error:");
	}
	
	MSG_DATA msginfo;
	msginfo.mtype = 5;//指定mtype
	strcpy(msginfo.message, "hello message!");
	if(msgsnd(msg_id,&msginfo,sizeof(msginfo.message),0)==-1)
	{
		perror("message send error:");
	}
	
	cout << "message send success" << endl;
	return 0;
}

消息队列接收端:


#include <iostream>
#include<unistd.h>//unix stand lib
#include<sys/types.h>
#include<sys/fcntl.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<dirent.h>//file dir
#include <sys/wait.h>//wait func
#include <stdlib.h>//ststem
#include <signal.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/shm.h>

using namespace std;
typedef struct
{
	long mtype;
	char message[50];
}MSG_DATA;


//========================================queue===============
int main(int argc, char *argv[])
{
	int msg_id;
	msg_id = msgget((key_t)1122, IPC_CREAT | 0666);
	if (msg_id == -1)
	{
		perror("msgget error:");
		return -1;
	}
	
	MSG_DATA msginfo;
	bzero(&msginfo,sizeof(msginfo));//清空用于接收
	
	if (msgrcv(msg_id, &msginfo, sizeof(msginfo.message), 5, IPC_NOWAIT) == -1)//msgrcv接收,mtype和发送的mtype不一样也可以收到
	{
		perror("message recv error:");
		return -1;
	}
	
	cout << "message recv " << msginfo.message<< endl;
	return 0;
}
  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论
请先登录 后发表评论~
©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页

打赏作者

z5z5z5z56

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值