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

本文深入讲解了消息队列这一进程间通信方式,包括其创建、发送和接收消息的基本原理及方法,通过具体代码实例展示了如何在Linux环境下使用msgget、msgsnd和msgrcv函数进行消息队列的创建和消息传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息队列介绍

消息队列: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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值