ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

进程间通信(二)消息队列

2019-03-03 20:04:26  阅读:287  来源: 互联网

标签:队列 msgid 间通信 int 消息 进程 msgsnd include


消息队列用于运行于同一台机器上的进程间通信,它和管道和相似,是一个在系统内核中用来保存消息的队列,它在系统内核中是以消息链表的形式出现。消息链表中节点的结构用msgmsgmsg声明。

消息队列

(1)创建新消息队列或取得已存在消息队列,函数原型:

int msgget(key_t key, int msgflg);
  • 1)参数keykeykey可以认为是一个端口号,也可以由函数ftokftokftok生成
  • 2)msgflgmsgflgmsgflg如果等于IPCIPCIPC_ CREATCREATCREAT,若没有该队列,则创建一个并返回新标识符,若已存在则返回原标识符;msgflgmsgflgmsgflg如果等于IPCIPCIPC_ EXCLEXCLEXCL,若没有该队列,则返回-1,若已存在,则返回0

(2)向队列读/写消息,函数原型如下所述:

msgrcvmsgrcvmsgrcv从队列中取用消息:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgsndmsgsndmsgsnd将数据放到消息队列中:

int msgsnd(int msqid, cosnt void *msgp, size_t msgsz, int msgflg);
  • 1)msqidmsqidmsqid是消息队列的标识码
  • 2)msgpmsgpmsgp是指向消息缓冲区的指针,此位置用来暂时存储发送和接收的信息,是一个用户可定义的通用结构,但一般定义为:
struct msgstru {
	long mtype;
	char mtext[512];
}
  • 3)msgszmsgszmsgsz是指消息的大小
  • 4)msgtypmsgtypmsgtyp是指从消息队列内读取的消息形态。如果值为0,则标识消息队列中的所有消息都会被读取
  • 5)msgflgmsgflgmsgflg:用来指明核心程序没有数据的情况下所应采取的行动。如果msgflgmsgflgmsgflg和常数IPCIPCIPC_ NOWAITNOWAITNOWAIT合用,则在msgsndmsgsndmsgsnd执行时若是消息队列已满,则msgsnd()msgsnd()msgsnd()将不会阻塞,而会立即返回-1,如果执行的是msgrcvmsgrcvmsgrcv,则在消息队列呈空时,不做等待马上返回-1,并设定错误码为ENOMSGENOMSGENOMSG.当msgflgmsgflgmsgflg为0时,msgsnd()msgsnd()msgsnd()及msgrcvmsgrcvmsgrcv在队列呈满或呈空的情形时,采取阻塞等待的处理模式

(3)设置消息队列属性,函数原型:

int msgctl(int msgqid, int cmd, struct msqid_ds *buf);
  • 参数中的msgctlmsgctlmsgctl系统调用对msgqidmsgqidmsgqid标识的消息队列执行cmdcmdcmd操作,系统定义了3种cmdcmdcmd操作:IPCIPCIPC_ STATSTATSTAT、IPCIPCIPC_ SETSETSET、IPCIPCIPC_ RMID。IPC$_ STATSTATSTAT用来获取消息队列中对应的msqidmsqidmsqid_ dsdsds数据结构,并将其保存到bufbufbuf指定的地址空间;IPCIPCIPC_ SETSETSET用来设置消息队列的属性,要设置的属性存储在bufbufbuf中;IPCIPCIPC_ RMID用来从内核中删除用来从内核中删除msqid$的消息队列

例1:用消息队列来传输数据

//msgreceive.cpp
/*************************************************************************
      > File Name: msgreceive.cpp
      > Author: ersheng
      > Mail: ershengaaa@163.com 
      > Created Time: Fri 01 Mar 2019 08:49:56 PM CST
 ************************************************************************/

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
using namespace std;
#define BUFSIZE 512
struct msg_st {
	long int msg_type;
	char text[BUFSIZE];
};
int main() {
	int running = 1;
	int msgid = -1;
	struct msg_st data;
	long int msgtype = 0;
	//建立消息队列 
	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if (msgid == -1) {
		fprintf(stderr, "msgget failed with errno: %d\n", errno);
		exit(EXIT_FAILURE);
	}
	//从队列中获取消息,直到遇到end消息为止 
	while (running) {
		if (msgrcv(msgid, (void *)&data, BUFSIZE, msgtype, 0) == -1) {
			fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
			exit(EXIT_FAILURE);
		}	
		printf("You wrote: %s\n", data.text);
		//遇到end结束 
		if (strncmp(data.text, "text", 3) == 0) {
			running = 0;
		}
	}
	//删除消息队列 
	if (msgctl(msgid, IPC_RMID, 0) == -1) {
		fprintf(stderr, "msgctl(IPC_RMID) failed\n");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}
//msgsend.cpp
/*************************************************************************
      > File Name: msgsend.cpp
      > Author: ersheng
      > Mail: ershengaaa@163.com 
      > Created Time: Fri 01 Mar 2019 09:01:07 PM CST
 ************************************************************************/

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
using namespace std;
#define MAX_TEXT 512
#define BUFSIZE 512
struct msg_st {
	long int msg_type;
	char text[MAX_TEXT];
};
int main() {
	int running = 1;
	struct msg_st data;
	char buffer[BUFSIZE];
	int msgid = -1;
	//建立消息队列 
	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if (msgid == -1) {
		fprintf(stderr, "msgget failed with error: %d\n", errno);
		exit(EXIT_FAILURE);
	}
	//向消息队列中写消息,直到写入end 
	while (running) {
		//输入数据 
		printf("Enter some text: ");
		fgets(buffer, BUFSIZE, stdin);
		data.msg_type = 1;
		strcpy(data.text, buffer);
		//向队列发送数据 
		if (msgsnd(msgid, (void *)&data, MAX_TEXT, 0) == -1) {
			fprintf(stderr, "msgsend failed\n");
			exit(EXIT_FAILURE);
		}
		//输入end结束输入 
		if (strncmp(buffer, "end", 3) == 0) {
			running = 0;
		}
		sleep(1);
	}
	exit(EXIT_SUCCESS);
}

在这里插入图片描述
在这里插入图片描述

消息队列与有名管道

相同点:

  • 1)消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接受的方式来传递数据的。
  • 2)在命名管道中,发送数据用writewritewrite函数,接受数据用readreadread函数,而在消息队列中,发送数据用msgsndmsgsndmsgsnd函数,接收数据用msgrcvmsgrcvmsgrcv函数,而且它们对每个数据都有一个最大长度的限制

不同点:

  • 1)消息队列也可以独立发送和接受进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难
  • 2)可以同时通过发送消息以避免命名管道的同步和阻塞问题,而不需要进程来提供同步方法
  • 3)接受程序可以通过消息类型有选择地接受数据,而不是像命名管道中那样,只能默认地接受

标签:队列,msgid,间通信,int,消息,进程,msgsnd,include
来源: https://blog.csdn.net/qq_38790716/article/details/88092758

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有