【Linux】IPC通信之消息队列

来源:互联网 发布:facebook程序员面试题 编辑:程序博客网 时间:2024/05/21 09:19

消息队列概念

消息队列提供了一个进程将一个数据块发送到另一个进程的方法。

相比于管道的同步与阻塞,消息队列很好的解决了这个问题

管道通信是基于字节流的,然而消息队列发送的是一个数据结构,即IPC对象

消息队列的总字节数是有上限的,消息队列的总数也是有一定上限的

IPC对象的内容(消息队列,信号量和共享内存共同的IPC对象)


消息队列的结构


与消息队列有关的函数

头文件

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

消息队列的创建

函数

int msgget(int key, int flags)

key是 int ftok(const char* pathname, int PROJ_ID)的返回值,其中pathname是路径名,PROJ_ID是工程号

flags有两个参数,分别是IPC_CREAT和IPC_EXCL

IPC_CREAT  单独使用时,创建一个IPC资源,如果资源已经存在,则获得当前存在的资源

IPC_EXCL     只有在共享内存不存在时进行创建,如果存在则会报错

当IPC_CREAT和IPC_EXCL共同使用时,返回一个新建的IPC标识符,如果IPC资源已经存在则返回-1,从而保证对象是新建产生的

消息队列的销毁

函数

int msgctl(int msg_id, int cmd, struct msqid_ds* buf)

msgctl系统调用对msgqid标识的消息队列执行cmd操作

系统定义的三种cmd操作:IPC_STAT,IPC_SET,IPC_RMID

IPC_STAT:获取msqid_ds数据结构,并保存到buf所指向的地址空间

IPC_SET:设置消息队列的属性,并存储到buf中

IPC_RMID:从系统中删除msgqid标识的消息队列

消息队列的发送

函数

int msgsnd(int msqid,const void* msgp,size_t msgsz,int msgflg)

msqid:消息队列的表识码

msgp:指向消息缓冲区的指针,来暂时存储发送和接受的消息,是一个用户自定义的数据结构

struct msgstru

{

long mType;

char mText[大小可变];

};

msgsz:消息队列的大小

msgflg:当msgflg为0时,msgsnd()或msgrcv()呈现满或者空的情形时,采取阻塞等待处理的模式

消息队列的接受

函数

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

msgtyp:表示从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都 会被读取。

Linux下查看系统中的IPC信息

ipcs -q

Linux下删除系统中的IPC信息

ipcrm -q

代码实现消息队列

comm.h

#include"comm.h"int main(){int msqid = CreatMsgQueue();if(msqid < 0){perror("CreatMsgQueue");return -1;}char buf[1024];while(1){buf[0] = 0;if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1){perror("RevMsg");return -2;}printf("Client# %s",buf);printf("Server Enter#");fflush(stdout);ssize_t s = read (0,buf,sizeof(buf)-1);if(s < 0){perror("read");return -3;}buf[s] = 0;if(SndMsg(msqid,SERVER_TYPE,buf) == -1){perror("SndMsg");return -4;}}DestoryMsgQueue(msqid);return 0;}

comm.c

#include"comm.h"int main(){int msqid = CreatMsgQueue();if(msqid < 0){perror("CreatMsgQueue");return -1;}char buf[1024];while(1){buf[0] = 0;if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1){perror("RevMsg");return -2;}printf("Client# %s",buf);printf("Server Enter#");fflush(stdout);ssize_t s = read (0,buf,sizeof(buf)-1);if(s < 0){perror("read");return -3;}buf[s] = 0;if(SndMsg(msqid,SERVER_TYPE,buf) == -1){perror("SndMsg");return -4;}}DestoryMsgQueue(msqid);return 0;}

client.c

#include"comm.h"int main(){int msqid = GetMsgQueue();if(msqid < 0){perror("GetMsgQueue");return -1;}char buf[1024];while(1){buf[0] = 0;printf("Client Enter# ");fflush(stdout);ssize_t s = read(0,buf,sizeof(buf)-1);if(s < 0){perror("read");return -2;}buf[s] = 0;if(SndMsg(msqid,CLIENT_TYPE,buf)<0){perror("SndMsg");return -3;}if(RcvMsg(msqid,SERVER_TYPE,buf)<0){perror("RcvMsg");return -4;}printf("Server echo# %s",buf);}return 0;}

server.c

#include"comm.h"int main(){int msqid = CreatMsgQueue();if(msqid < 0){perror("CreatMsgQueue");return -1;}char buf[1024];while(1){buf[0] = 0;if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1){perror("RevMsg");return -2;}printf("Client# %s",buf);printf("Server Enter#");fflush(stdout);ssize_t s = read (0,buf,sizeof(buf)-1);if(s < 0){perror("read");return -3;}buf[s] = 0;if(SndMsg(msqid,SERVER_TYPE,buf) == -1){perror("SndMsg");return -4;}}DestoryMsgQueue(msqid);return 0;}

makefile

#include"comm.h"int main(){int msqid = CreatMsgQueue();if(msqid < 0){perror("CreatMsgQueue");return -1;}char buf[1024];while(1){buf[0] = 0;if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1){perror("RevMsg");return -2;}printf("Client# %s",buf);printf("Server Enter#");fflush(stdout);ssize_t s = read (0,buf,sizeof(buf)-1);if(s < 0){perror("read");return -3;}buf[s] = 0;if(SndMsg(msqid,SERVER_TYPE,buf) == -1){perror("SndMsg");return -4;}}DestoryMsgQueue(msqid);return 0;}

运行结果



原创粉丝点击