一.IPC主题之消息队列
- 消息队列:一个进程向另一个进程提供有类型数据块的模板。
- 数据块:例如 一边发一百个字节的数据块,则另一边接收一百个字节的数据块,少了任何一部分,这一块都是无效的。而流是写多少读多少,传的数据无明显的格式要求。
- 内核为每个IPC对象维护一个数据结构
struct ipc_prem()//围绕着消息队列的权限问题的源信息
{
...
};
- 每一个IPC特有一个数据结构
struct msgid_ds{//用来描述队列的信息,可以用它来设置 获取 调整操作系统内部消息队列源信息
...
}
二.用代码实现消息队列
1.创建消息队列
所用到的函数:
2.获取消息队列
所用到的函数和创建所用到的一样。
3.发送消息队列
所用到的函数如下图:
4.接收消息
所用到的函数:
5.销毁消息队列
所用到的函数:
三.源代码
- comm.h
#ifndef __COMM_H__
#define __COMM_H__
#include<stdio.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<errno.h>
#include<string.h>
#define SERVER_TYPE 1
#define CLIENT_TYPE 2
#define PATHNAME "."
#define PROJ_ID 0x6666
#define SIZE 128
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[SIZE]; /* message data */
};
int CreatmesQueue();
int GetmesQueue();
int SentmesQueue(int mspid,long type,const char* _info);
int ReceivermesQueue(int msgid,long type,char out[]);
int DestorymesQueue(int mspid);
#endif
- comm.c
#include"comm.h"
int comm_que(int msflg)
{
int key=ftok( PATHNAME,PROJ_ID);
if(key<0)
{
perror("ftok");
return -1;
}
int mspid=msgget(key,msflg);
if(mspid<0)
{
perror("mesget");
return -2;
}
return mspid;
}
int CreatmesQueue()
{
return comm_que(IPC_CREAT|IPC_EXCL|0666);
}
int GetmesQueue()
{
return comm_que(IPC_CREAT);
}
int SentmesQueue(int mspid,long type,const char* _info)
{
struct msgbuf buf;
buf.mtype=type;
strcpy(buf.mtext,_info);
if(msgsnd(mspid,&buf,sizeof(buf.mtext),0)<0)
{
perror("msgsnd");
return -1;
}
return 0;
}
int ReceivermesQueue(int msgid,long type,char out[])
{
struct msgbuf buf;
if(msgrcv(msgid,&buf,sizeof(buf.mtext),type,0)<0)
{
perror("msgrcv");
return -1;
}
strcpy(out,buf.mtext);
return 0;
}
int DestorymesQueue(int mspid)
{
if(msgctl(mspid,IPC_RMID,NULL)<0)
{
perror("msgctl");
return -1;
}
}
- server.c
#include"comm.h"
int main()
{
int msgid=CreatmesQueue();
char out[SIZE];
while(1)//receive->send
{
ReceivermesQueue(msgid,CLIENT_TYPE,out);
printf("client>%s\n",out);
printf("Please enter $:");
fflush(stdout);
ssize_t s=read(0,out,sizeof(out)-1);
if(s > 0)
{
out[s-1]='\0';
SentmesQueue(msgid,SERVER_TYPE,out);
}
}
DestorymesQueue(msgid);
return 0;
}
- client.c
#include"comm.h"
int main()
{
int msgid=GetmesQueue();
char out[SIZE];
while(1)//sent->rece
{//send
printf("please enter $: ");
fflush(stdout);
ssize_t s=read(0,out,sizeof(out)-1);
if(s>0)
{
out[s-1]='\0';
SentmesQueue(msgid,CLIENT_TYPE,out);
}
//rece
ReceivermesQueue(msgid,SERVER_TYPE,out);
printf("server >%s\n",out);
}
return 0;
}
- Makefile
client_=client
server_=server
cc=gcc
cliSrc=client.c comm.c
serSrc=server.c comm.c
.PHONY:all
all:$(client_) $(server_)
$(client_):$(cliSrc)
$(cc) -o $@ $^
$(server_):$(serSrc)
$(cc) -o $@ $^
.PHONY:clean
clean:
rm -f $(client_) $(server_)
四.运行结果图
server.c运行结果图
client.c运行结果图