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

进程通行(IPC)--实现消息队列及验证

2017-05-26 21:28 411 查看
今天我们来分享一下进程通行(IPC)-实现消息队列。
消息队列由操作系统提供一个链表(也就是说消息队列需要操作系统接口),以链表节点为一个数据块(有类型),基于消息,每条消息有上限且消息的总数也是有限的。

与管道通行的区别是,管道通信以字节流为通信单位,消息队列是以有类型的数据块为通信单位。

消息队列实现原理:

一个进程建立消息队列(本文为serves),另一个进程(本文为client)打开该消息队列即可。此后两个进程可以相互读写以此来进行通信。

消息队列实现步骤:

1》建立(打开)消息队列

2》发送消息/接收消息

3》接收消息/发送消息

4》销毁消息队列(谁建立谁销毁)

进行传递消息的数据块(结构体)如下示:

   struct msgbuf{

       long mtype;//消息的发起者的类型(标志)

       char mtext[1024];//消息内容

   };

消息队列是随内核的,除了需要调用系统接口去建立消息队列,还需要调用系统接口去销毁消息队列。

最后,介绍关于查看消息队列和销毁消息队列的系统命令,截图如下:


 
代码和运行结果如下:

Commom.h

#ifndef _COMMOM_H_
#define _COMMOM_H_

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<unistd.h>

struct msgbuf{
long mtype;
char mtext[1024];
};

#define PATHNAME "."
#define PROJ_ID 0x6666

#define SERVE 1
#define CLIENT 2

int CreatMsgQueue();
int GetMsgQueue();
int SendMsgQueue(int msgid, int who, char* msg);
int RecvMsgQueue(int msgid, int recvtype, char* out);
int DestroyMsgQueue(int msgid);

#endif


Commom.c

#include"commom.h"

int commMsgQueue(int flags)
{
key_t keys = ftok(PATHNAME, PROJ_ID);
if(keys<0){
perror("ftok");
return -2;
}

int msgid = msgget(keys, flags);
if(msgid <0){
perror("msgget");
return -1;
}
return msgid;
}

int CreatMsgQueue()
{
return commMsgQueue(IPC_CREAT|IPC_EXCL);
}
int GetMsgQueue(){
return commMsgQueue(IPC_CREAT);
}
int SendMsgQueue(int msgid, int who, char* msg){
struct msgbuf buf;
buf.mtype = who;
strcpy(buf.mtext,msg);

Int flag = msgsnd(msgid,(void*)&buf, sizeof(buf.mtext),0);
if(flag<0){
perror("msgsnd");
return -4;
}
return 0;
}
int RecvMsgQueue(int msgid, int recvtype, char* out){
struct msgbuf buf;
ssize_t s = msgrcv(msgid,(void*)&buf, sizeof(buf.mtext), recvtype, 0);
if(s<0){
perror("msgvcv");
return -5;
}

strcpy(out, buf.mtext);
return s;
}
int DestroyMsgQueue(int msgid){
int flag = msgctl(msgid, IPC_RMID, NULL);
if(flag<0){
perror("");
return -3;
}
return 0;
}


Client.c

  

#include"commom.h"
#include"commom.c"

int main(){
int msgid = GetMsgQueue();

char msg[1024];
while(1){
int r = RecvMsgQueue(msgid, SERVE,msg);
if(r<0){
perror("recv wrong");
return -3;
}
printf("serve say:%s\n", msg);

printf("please write: ");
fflush(stdout);
ssize_t s=read(0, msg, sizeof(msg)-1);
if(s<0){
perror("fread");
return -1;
}
msg[s-1] = 0;

int k = SendMsgQueue(msgid, CLIENT, msg);
if(k<0){
perror("send wrongs");
return -2;
}
}

return 0;
}


Serves.c

#include"commom.h"
#include"commom.c"

int main(){
umask(0);
int msgid = CreatMsgQueue();

char msg[1024];
while(1){
printf("please write: ");
fflush(stdout);
ssize_t s=read(0, msg, sizeof(msg)-1);
if(s<0){
perror("fread");
return -1;
}
msg[s-1] = 0;

int k = SendMsgQueue(msgid, SERVE, msg);
if(k<0){
perror("send wrongs");
return -2;
}
int r = RecvMsgQueue(msgid, CLIENT,msg);
if(r<0){
perror("recv wrong");
return -3;
}
printf("client say:%s\n", msg);
}

DestroyMsgQueue(msgid);
return 0;
}


Makefile

.PHONY:all
all:client serve

client:client.c  commom.h
gcc -o $@ $^
serve:serves.c  commom.h
gcc -o $@ $^

.PHONY:clean
clean:
rm -f client serve


运行界面(先运行serve再运行client)


 
 


 

分享如上,如有错误望指针,共同学习!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ipc Linux 进程通信