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

消息队列介绍

消息队列: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;
}
  • 9
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
消息队列IPC机制中的一种,消息队列允许不同进程间传递数据。在Linux中,使用消息队列需要使用到两个系统调用函数msgsndmsgrcv。 1. msgsnd函数原型和参数说明: ```c #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ``` - msqid:消息队列标识符,由msgget函数返回。 - msgp:指向要发送的消息结构体的指针。 - msgsz:要发送的消息结构体的大小。 - msgflg:消息标志位,可以是0或IPC_NOWAIT。如果为0,则进程将会阻塞,直到消息被成功发送或者出现错误;如果为IPC_NOWAIT,则进程不会阻塞,而是立即返回-1并设置errno为EAGAIN。 2. msgrcv函数原型和参数说明: ```c #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); ``` - msqid:消息队列标识符,由msgget函数返回。 - msgp:指向用于接收消息的缓冲区指针。 - msgsz:接收缓冲区的大小。 - msgtyp:指定要接收的消息类型。如果为0,则接收队列中的第一个消息;如果大于0,则接收队列中第一个类型为msgtyp的消息;如果小于0,则接收队列中的第一个类型值小于或等于msgtyp的消息。 - msgflg:消息标志位,可以是0或IPC_NOWAIT。如果为0,则进程将会阻塞,直到消息被成功接收或者出现错误;如果为IPC_NOWAIT,则进程不会阻塞,而是立即返回-1并设置errno为EAGAIN。 注意:msgsndmsgrcv函数的msgp参数指向的结构体必须符合以下格式: ```c struct mymsgbuf { long mtype; char mtext[1]; } ``` 其中,mtype为消息类型,mtext为消息内容。mtext数组的长度应该保证足够存储实际消息的长度。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值