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

本文详细介绍了Linux进程通信中消息队列的工作原理和实现步骤。区别于管道通信的字节流,消息队列以有类型的数据块作为通信单位。内容包括消息队列的创建、使用和销毁,并提供了相关结构体定义。通过示例代码和运行结果展示,帮助读者理解消息队列的使用方法。

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

今天我们来分享一下进程通行(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)

 

 

 

分享如上,如有错误望指针,共同学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值