消息缓冲是UNIX系统进程之间进行大量数据交换的机制之一。消息缓冲是基于消息队列的。发送进程将消息挂入接收进程的消息队列,接收进程从消息队列中接收消息。消息是指具有类型和数量的一个数据。消息分共有和私有的,如果消息为私有的,只能被创建消息队列的进程和其子进程访问;如果是公有的,可以被系统中知道消息队列名的所有进程访问。消息可以按类型访问,因此,不必按序访问。关于这方面的好多知识,我也不是特别了解,有需要的可以自行Google.

为了理解进程利用消息缓冲的通信过程,下面给出两个例子

一、创建一个私有消息队列,一个进程自己发送消息和接收消息。创建一个消息队列,之后将一个消息“hello,world”放入消息队列。在从消息队列进行接收,并打印出所接受的消息。

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#define _USE_GNU
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
struct msgbuf{
    long mtype;
    char mtext[500];
};
int main(int argc,char *argv[])
{
   int queue_id;
   struct msgbuf * msg,*recv_msg;
   int rc;
   int msgsz;
   queue_id=msgget(IPC_PRIVATE,IPC_CREAT|0600);
   if(queue_id==-1){
      perror("main's msgget");
      exit(1);
   }
   printf("the created message's id ='%d'.\n",queue_id);
   //分配一个消息结构"Hello World!"
   msg = (struct msgbuf *)malloc(sizeof(struct msgbuf)+strlen("hello,world"));
   msg -> mtype = 1;//消息队列的索引赋值为1
   strcpy(msg -> mtext,"hello world");//将字符串复制到消息体中
   //发送消息
   rc = msgsnd(queue_id,msg,strlen(msg -> mtext) + 1,0);
   //这里的+1是指字符串的结束符
   if(rc == -1){
    perror("msgsnd");
    exit(1);
   }
   else
    printf("%d\n",rc);
   free(msg);//释放消息占用的空间
   printf("message is placed on message's queue\n");
   //接收消息
   recv_msg = (struct msgbuf *)malloc(sizeof(struct msgbuf)+strlen("hello world")+1);
   msgsz = strlen(recv_msg -> mtext) + 1;
   rc = msgrcv(queue_id,recv_msg,msgsz,0,0);
  if(rc == -1){
   perror("msgrcv");
   exit(1);
}
    printf("received message's mtype is'%ld';mtext if '%s' \n",recv_msg->mtype,recv_msg->mtext);
   msgctl(queue_id,IPC_RMID,NULL);//删除消息队列
   return 0;
}



消息队列和缓存的区别 消息缓冲队列_#define



二、创建一个公共消息队列,实现客户进程和服务者进程之间进行通信

  客户进程向服务者进程发送消息,请求服务。服务者进程接受消息,完成客户的服务请求后,再将服务结果以消息方式发送给客户。其具体实现描述为:

①服务者进程用关键字SVKEY和标志IPC_CREAT调用magget()建立一个消息队列,得到队列的标识符msgid之后,用msgid调用msgrcv()接受类型为REQ的消息。

②客户进程用关键字SVKEY调用msgget()得到消息队列标识符msgid,之后用msgid调用msgsnd()将自己的pid发送到消息队列(SVKEY)中,表示其所请求的服务。然后调用msgrcv()等待服务结果消息的到来。

③服务者进程接收到请求服务的消息后进行服务工作,完成服务后向客户进程发回一条消息,消息的类型为客户的标识pid,消息正文是服务者进程自己的标志pid,

④客户进程收到服务结果消息后,显示必要消息后,结束两者的通信过程。

客户进程的通信过程

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#define SVKEY 75
#define REQ 1
struct msgform{
    long mtype;//消息类型
    char mtext[256];//消息正文
};
int main()
{
    struct msgform msg;
    int msgid;
    int pid;
    int *pint;
    msgid = msgget(SVKEY,0777);
    pid = getpid();//获得当前进程标识
    pint = (int *)msg.mtext;//取消息正文的首地址
    *pint = pid;//将客户进程的pid复制到消息缓冲区
    msg.mtype = REQ;
    msgsnd(msgid,&msg,sizeof(int),0);
    msgrcv(msgid,&msg,256,pid,0);//这里的pid作为消息类型
    printf("client receive server's service result is server's pid :%d.\n",*pint);
    return 0;
}



服务者进程的通信过程

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#define SVKEY 75
#define REQ 1
struct msgform{
    long mtype;
    char mtext[256];
};
int main()
{
    struct msgform msg;
    int i;
    int msgid;
    int pid;
    int *pint;
    msgid = msgget(SVKEY,0777|IPC_CREAT);
    for(;;)
    {
        msgrcv(msgid,&msg,256,REQ,0);
        printf("server is doing the service for a client.\n");
        pint = (int *)msg.mtext;
        pid = *pint;//获得客户进程的pid,以便进行服务
        printf("server receive client's service request is client's pid:%d.\n",pid);
        msg.mtype = pid;
        *pint = getpid();
		//将服务者服务结果的pid发送给客户
        msgsnd(msgid,&msg,sizeof(int),0);
    }
    return 0;
}



消息队列和缓存的区别 消息缓冲队列_消息队列_02