【Linux】消息队列

一、消息队列

1.消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。
2.每个数据块都被认为是有一个类型,接受者进程的数据块可以有不同的类型值。
3.消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。


IPC对象数据结构:
这里写图片描述

消息队列结构:
这里写图片描述

二、消息队列函数:

1.msgget函数:
这里写图片描述
2.mstctl函数:
这里写图片描述
3.msgsnd函数:
这里写图片描述
这里写图片描述
4.msgrcv函数:
这里写图片描述
注:
这里写图片描述


三、代码示例

查看与删除消息队列的命令:
(1)查看已创建的消息队列:
ipcs -q
(2)删除已存在的消息队列
ipcrm -q 163840(消息队列的标识符) ( 删除一个消息队列 )
ipcrm -a (删除所有创建了的消息队列)

【comm.h】

#ifndef _COMM_H_
#define _COMM_H_

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>

#define PATHNAME "."   //"."表示当前目录
#define PROJ_ID 0x6666   //权限设置 6(文件类型)|6(拥有者权限rw-)|6(用户组权限rw-)|6(其他的权限rw-)

#define SERVER_TYPE 1    //TYPE必须设置成一个大于0的数
#define CLIENT_TYPE 2

struct msgbuf{
    long mtype;
    char mtext[1024];
};

int createMsgQueue();   //创建消息队列
int getMsgQueue();     //代开消息队列
int destoryMsgQueue(int msgid);  //销毁一个存在的消息队列
int sendMsg(int msgid,int who,char* msg);   //向消息队列发送信息
int recvMsg(int msgid,int recvType,char out[]);   //从消息队列中读取数据

#endif

【comm.c】

#include"comm.h"

//success -->(>0)  falied -->(-1)

static int commMsgQueue(int flags)
{
    key_t _key=ftok(PATHNAME,PROJ_ID);   //通过ftok获取一个唯一标识符
    if(_key<0)
    {
        perror("fotk");
        return -1;
    }

    int msgid=msgget(_key,flags);
    if(msgid<0)
        perror("msgget");

    return msgid;
}
int createMsgQueue()
{
    return commMsgQueue(IPC_CREAT|IPC_EXCL|0666);  //IPC_CREAT如果存在,打开它,如果不存在创建一个;
                                                  //IPC_EXCL 如果消息队列不存在,看不见,如果存在失败。
}

int getMsgQueue()
{
    return commMsgQueue(IPC_CREAT);
}

int destoryMsgQueue(int msgid)
{
    if(msgctl(msgid,IPC_CREAT,NULL)<0)
    {
        perror("msgctl");
        return -1;
    }
    return 0;
}

int sendMsg(int msgid,int who,char* msg)
{
    struct msgbuf buf;
    buf.mtype=who;
    strcpy(buf.mtext,msg);

    if(msgsnd(msgid,(void *)&buf,sizeof(buf.mtext),0)<0)
    {
        perror("msgsnd");
        return -1;
    }
    return 0;
}
int recvMsg(int msgid,int recvType,char out[])
{
    struct msgbuf buf;
    if(msgrcv(msgid,(void*)&buf,sizeof(buf.mtext),recvType,0)<0)
    {
        perror("msgrcv");
        return -1;
    }
    strcpy(out,buf.mtext);
    return 0;
}

【server.c】

#include"comm.h"

int main()
{
    int msgid=createMsgQueue();

    char buf[1024];
    while(1)
    {
        buf[0]=0;
        recvMsg(msgid,CLIENT_TYPE,buf);   //从消息队列中读取数据
        printf("client# %s\n",buf);

        printf("Please Enter#");
        fflush(stdout);
        size_t s=read(0,buf,sizeof(buf));
        if(s>0)
        {
            buf[s-1]=0;
            sendMsg(msgid,SERVER_TYPE,buf);     //向消息队列发送信息
            printf("send done,wait recv...\n");
        }
    }
    destoryMsgQueue(msgid);   //销毁一个已存在的消息队列
    return 0;
}

【client.c】

#include"comm.h"

int main()
{
    int msgid=getMsgQueue();

    char buf[1024];
    while(1)
    {
        buf[0]=0;
        printf("Please Enter# ");
        fflush(stdout);
        size_t s=read(0,buf,sizeof(buf));
        if(s>0)
        {
            buf[s-1]=0;
            sendMsg(msgid,CLIENT_TYPE,buf);
            printf("send done,wait recv...\n");
        }

        recvMsg(msgid,SERVER_TYPE,buf);
        printf("server# %s\n",buf);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值