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

本文介绍消息队列作为一种进程间通信机制的基本原理及其实现方式。消息队列允许不同进程间通过发送不同类型的消息进行通信,避免了命名管道的同步和阻塞问题。文章提供了消息队列创建、发送和接收消息的具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息队列:消息队列提供了一种从⼀个进程向另⼀个进程发送⼀个数据块的⽅方法。每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值。可以通过发送消息来避免命名管道的同步和阻塞问题。
特点:基于消息;是用链表实现的;生命周期随内核
每个消息的最⼤大长度是有上限的(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_)

运行结果如下所示
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值