Linux进程间通信之消息队列

消息队列的特点
1、生命周期随内核
2、双向通信
3、按块大小读写//不像管道是面向字节流的
这些接口都是System V标准
消息队列的创建:

 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 int msgget(key_t key, int msgflg);

key代表要创建的消息队列的标识
msgflag通常是通过IPC_CREAT或者IPC_EXCL来设置的
IPC_CREAT|IPC_EXCL代表创建消息队列,如果这个消息队列已经存在,则立即出错返回
IPC_CREAT则代表创建消息队列,不存在则创建,存在则直接打开

key值的创建:使用ftok函数,在之后的信号量还有共享内存中也要用到

#include <sys/types.h>
 #include <sys/ipc.h>
 key_t ftok(const char *pathname, int proj_id);//第一个参数代表路径,第二个参数代表权限

消息队列的删除:

 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 int msgctl(int msqid, int cmd, struct msqid_ds *buf);//用于删除一个消息队列

msqid表示要删除的消息队列的标识
cmd:cmd设置成为IPC_RMID
buf:通常buf设置为NULL

想消息队列中发送消息使用msgsnd

#include <sys/types.h>
 #include <sys/ipc.h>
  #include <sys/msg.h>
 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
 The msgp argument is a pointer to caller-defined structure of the following general form:

           struct msgbuf {
               long mtype;       /* message type, must be > 0 */类型必须大于0
               char mtext[1];    /* message data */块大小
           };
需要自定义

从消息队列中接受消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);和msgsnd相似

双向通信的具体实现:

server.c
#include"comm.h"
int main()
{
     int msgid=CreateMsgQueue();
     char buf[1024]={0};
    while(1)
     {
          RecvMsg(msgid,CLIENT_TYPE,buf);
          printf("client say :%s\n",buf);
          ssize_t s=read(0,buf,sizeof(buf)-1);
          if(s>0)
          {
               buf[s-1]=0;
               SendMsg(msgid,SERVER_TYPE,buf);
          }
     }
     Destroy(msgid);
     return 0;
}

client.c
#include"comm.h"
int main()
{
     int msgid=GetMsgQueue();
     char buf[1024]={0};
    while(1)
     {   
           ssize_t w = read(0,buf,sizeof(buf)-1);
          if(w>0)
          {
            buf[w-1]=0;
           SendMsg(msgid,CLIENT_TYPE,buf);
     }

          RecvMsg(msgid ,SERVER_TYPE,buf);
          printf("Server say:%s\n",buf);
     }
     return 0;
}

comm.c
#include"comm.h"
int ComMsgQueue(int flag)
{
     key_t key=ftok(PATHNAME,PROJ_ID);
     if(key<0)
     {
          perror("ftok");
          return -1;
     }
     int msgid=msgget(key,0666|flag);
     if(msgid<0)
     {
          perror("msgget");
          return -2;
     }
     return msgid;
}
int CreateMsgQueue()
{
   return ComMsgQueue(IPC_CREAT|IPC_EXCL);
}
int GetMsgQueue()
{
     return ComMsgQueue(IPC_CREAT);
}
int DestroyMsgQueue(int msgid)
{

     if(msgctl(msgid,IPC_RMID,NULL)<0)
     {
          perror("msgctl");
          return -1;
     }
    return 0;
}
int SendMsg(int msgid,int type,const char*msg)
{
   struct msgbuf _mb;
   _mb.mytype=type;
   strcpy(_mb.mtext,msg);
   if(msgsnd(msgid,&_mb,sizeof(_mb.mtext),0)<0)
   {
     perror("msgsnd");
     return -1;
   }
   return  0;
}
int RecvMsg(int msgid,int type,char*out)
{
   struct msgbuf _mb;
   if(msgrcv(msgid,&_mb,sizeof(_mb.mtext),type,0)<0)
   {
        perror("msgrcv");
        return -1;
   }
   strcpy(out,_mb.mtext);
   return 0;
}

comm.h
#ifndef _COMM_H_
#define _COMM_H_
#define SERVER_TYPE 1
#define CLIENT_TYPE 2
#define PATHNAME "."
#define PROJ_ID 0x6666
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include<stdio.h>
struct msgbuf
{
     long mytype;
     char mtext[1024];
};
int CreatMsgQueue();
int DestroyMsgQueue();
int SendMsg();
int RecvMsg();
int GetMsgQueue();
#endif

查看消息队列的指令 ipcs -q
删除消息队列的指令 ipcrm -q +msqid

这里写图片描述
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值