进程间通信——消息队列
来源:互联网 发布:手机知乎怎么提问 编辑:程序博客网 时间:2024/05/17 23:03
前言
进程间需要进程通信进行数据传输和资源共享,另外一个进程在很多时候需要向另外的一个进程通知事件,有时候进程之间存在关系,需要去控制另外的一个进程,所以进程通信是很需要的。
进程间通信的第一种就是消息队列
什么是消息队列
消息队列是消息的链表,存放在内核当中,由消息队列标识符标识,消息队列提供一种进程之间数据块传送的方法,每个数据块都被认为是一种类型。每个进程都有一个与之相关联的消息队列,其功能就类似于一个信箱
注意
因为管道是随进程的,进程结束管道生命周期也就结束,而对于消息队列来说,是随操作系统的,就算进程突出,不去手动的释放消息队列,消息队列依然是存在的。
我们可以使用ipcs -q
进行查看操作系统的消息队列,使用ipcrm -q msgid
进行销毁消息队列。
消息队列的创建
使用msgget函数,我们可以创建或者访问一个消息队列,
在创建消息队列之前我们依然要用ftok得到一个key标识符。
key_t ftok(const char *pathname, int proj_id);
这里的pathname是路径,proj_id用来指定数字,为生成唯一的key提供。该函数把从pathname导出的信息与id的低序8位组合成⼀个整数IPC键。
然后创建队列。
int msgget(key_t key, int msgflg);
msgflg使用IPC_CREATE和IPC_EXCL进行创建消息队列,当msgflg使用IPC_CREATE和0的时候,这个时候使用消息队列。
函数返回值返回一个msgid,失败返回-1。
发送消息和接受消息
使用消息队列当然涉及到发送消息和接受消息,msgsnd函数和msgrcv函数提供了这两个功能,
首先来看msgsnd函数
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
在这里我们需要关注第二个参数,第二个参数是指向一个结构体的一个指针,这个结构体叫做 struct msgbuf
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[用户指定大小]; /* message data */ };
这个结构体第一个变量是消息的类型,第二个是存放消息的数组。
这个结构体早sys/msg.h当中已经有定义,所以我们可以直接拿来用就行。
然后看msgsnd的后面两个参数:
msgsz是注意是消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度,是指第二个参数制作指向的消息长度。
msgflg,用来指明在没有数据的情况下所需要做的操作,这个操作我们经常使用IPC_NOWAIT,这样当消息队列满了的时候,再向消息队列中发送消息,不会发生阻塞现象。
当调用成功,这个时候消息数据将被拷贝放入到消息队列中
接收消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgrcv函数第二个参数,同样是指向消息队列结构体的指针,第三个参数和第四个也和上述是一样的。
当调用成功的时候,返回消息队列接受缓存当中的字节数,消息复制到用户缓冲区,然后删除消息队列当中的对应的信息。
控制消息队列
控制消息队列需要使用的函数是msgctl函数,
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
这个函数中的cmd参数提供需要的操作,例如使用IPCRMID就可以进行删除消息队列。
示例:
我们使用服务器进程进行创建消息队列,然后使用客户进程进行send数据,服务进程接收数据。
comm.h
#ifndef __COMM_H__#define __COMM_H__#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/types.h>#include<string.h>#include<time.h>#define _MSG_SIZE_ 1024#define FILEPATH "."#define PROJID 0#define PERM 0666#define SERVER_TYPE 1#define CLIENT_TYPE 2#define MYSIZE 128struct msgbuf{ long mtype; char mtext[MYSIZE];};static int commmsg(int msgflg);int createmsg();int sendmsg(int msgid,long type,const char * msg);int getmsg();int recvmsg(int msgid,int type,char out[]);int destorymsg(int msgid);#endif //!__COMM_H__
comm.c
#include"comm.h"static int commmsg(int msgflg){ key_t key=ftok(FILEPATH,PROJID); if(key<0) { perror("ftok"); return -1; } int msqid=msgget(key,msgflg); if(msqid<0) { perror("msgget"); return -2; } return msqid;}int createmsg(){ return commmsg(IPC_CREAT|IPC_EXCL|PERM); }int getmsg(){ return commmsg(0);}int sendmsg(int msgid,long type,const char *msg){ struct msgbuf buf; buf.mtype=type; strcpy(buf.mtext,msg); int id=msgsnd(msgid,&buf,sizeof(buf.mtext),0); if(id<0) { perror("msgsnd"); return -1; } return 0;}int recvmsg(int msgid,int type,char out[]){ struct msgbuf buf; int size=msgrcv(msgid,&buf,sizeof(buf.mtext),type,0); if(size>0) { //buf.mtext[size]='\0'; strncpy(out,buf.mtext,size); return 0; } perror("msgrcv"); return -1;}int destorymsg(int msgid){ if(msgctl(msgid,IPC_RMID,NULL)<0) { perror("msgctl"); return -1; } return 0;}
client.c
#include"comm.h"int main(){ int msqid=getmsg(); char buf[MYSIZE]; char out[2*MYSIZE]; while(1){ printf("please input:"); fflush(stdout); ssize_t _s=read(0,buf,sizeof(buf)-1); if(_s>0) { buf[_s]='\0'; sendmsg(msqid,CLIENT_TYPE,buf); } if(recvmsg(msqid,SERVER_TYPE,out)<0) { break; } printf("server echo :%s\n",out); } return 0;}
server.c
#include"comm.h"int main(){ int msqid=createmsg(); char buf[2*MYSIZE]; while(1){ if(recvmsg(msqid,CLIENT_TYPE,buf)<0) { break; } printf("client# %s\n",buf); if(sendmsg(msqid,SERVER_TYPE,buf)<0) { break; } } destorymsg(msqid); return 0;}
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信——消息队列
- 进程间通信—消息队列
- 进程间通信——消息传递(消息队列)
- Linux进程通信——消息队列
- 进程通信2——消息队列
- MySQL 常用数据类型
- 常见的关于avaScript 面试题(上)
- DOM操作
- 递归【汉诺塔】
- Android通过Messager跨进程通信初探
- 进程间通信——消息队列
- leetcode-326-Power of Three
- 故障诊断技术
- rtmp抓包分析
- 基于AVPlayer的音乐播放器,支持上下曲,随机播放,后台播...
- POJ 2096 Collecting Bugs 概率DP(期望)
- MySQL 基本操作
- Calendar类的小测试
- Activiti工作流框架学习(一)——环境的搭建和数据表的了解