您的位置:首页 > 运维架构 > Linux

进程间通信(四)------消息队列

2017-03-21 15:52 351 查看
消息队列:消息队列提供了一种从⼀个进程向另⼀个进程发送⼀个数据块的⽅方法。每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值。可以通过发送消息来避免命名管道的同步和阻塞问题。

特点:基于消息;是用链表实现的;生命周期随内核

每个消息的最⼤大长度是有上限的(MSGMAX)

每个消息队列的总的字节数是有上限的(MSGMNB)

系统上消息队列的总数也有⼀一个上限(MSGMNI)



内核为每个IPC对象维护一个数据结构,消息队列,共享内存和信号量都有这样⼀个共同的数据结构:



comm.h

#ifndef _COMM_H_
#define _COMM_H
#define PATHNAME "."
#define PROJ_ID 0x666
#define SIZE 128
#define SEVER_TYPE 1
#define CLIENT_TYPE 2
struct msgbuf
{
long int mtype; /* type of received/sent message*/
char mtext[SIZE];  /* text of the message*/
};
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
int createMsg();
int commMsg(int flags);
int getMsg();
int sendMsg(int msgid,long type,const char *_info);
int recvMsg(int msgid,long type,char out[]);
int destroyMsg(int msgid);
#endif


comm.c

#include"comm.h"
int commMsg(int flags)
{

key_t key=ftok(PATHNAME,PROJ_ID);
if(key<0)
{
perror("ftok");
return -1;
}
int msgid=msgget(key,flags);
if(msgid<0)
{
perror("msgget");
return -2;
}
return msgid;
}
int createMsg()
{
return commMsg(IPC_CREAT | IPC_EXCL | 0666);
}
int getMsg()
{
return commMsg(IPC_CREAT);
}
int sendMsg(int msgid, long type,const char *_info)
{
struct msgbuf msg;
msg.mtype=type;
strcpy(msg.mtext,_info);
msgsnd(msgid,&msg,sizeof(msg.mtext),0);
if(msgsnd<0)
{
perror("msgsnd");
return -1;
}
return 0;
}
int recvMsg(int msgid,long type,char out[])
{
struct msgbuf msg;
if(msgrcv(msgid,&msg,sizeof(msg.mtext),type,0)<0)
{
perror("msgrcv");
return -1;
}
strcpy(out,msg.mtext);
return 0;
}
int destroyMsg(int msgid)
{
if(msgctl(msgid,IPC_RMID,NULL)<0)
{
perror("msgctl");
return -1;
}
return 0;
}


sever.c

#include"comm.h"
int main()
{
int msgid=createMsg();
printf("msgid=%d\n",msgid);
sleep(3);
int i=0;
long type=SEVER_TYPE;
const char *msg="hello world";
char buf[SIZE];
while(1)
{
//recv->send
recvMsg(msgid,CLIENT_TYPE,buf);
printf("client# %s\n",buf);
printf("Please Enter$ ");
fflush(stdout);
size_t s=read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1]='\0';
sendMsg(msgid,SEVER_TYPE,buf);
}
}
sleep(3);
destroyMsg(msgid);
return 0;
}


client.c

#include"comm.h"
int main()
{
int msgid=getMsg();
printf("msgid=%d\n",msgid);
int i=0;
long type=SEVER_TYPE;
const char *msg="hello world";
char buf[SIZE];
while(1)
{
//send->recv
printf("Please Enter$ ");
fflush(stdout);
size_t s=read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1]='\0';
sendMsg(msgid,CLIENT_TYPE,buf);
}
recvMsg(msgid,SEVER_TYPE,buf);
printf("sever# %s\n",buf);
}
//destroyMsg(msgid);
return 0;
}


Makefile

client_=client
sever_=sever
cc=gcc
cliSrc=client.c comm.c
seSrc=sever.c comm.c
.PHONY:all
all:$(client_) $(sever_)
$(client_):$(cliSrc)
$(cc) -o $@ $^
$(sever_):$(seSrc)
$(cc) -o $@ $^
.PHONY:clean
clean:
rm -f $(client_) $(sever_)


运行结果如下所示



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息