Linux消息队列

  1. 消息队列
    链式队列
    在这里插入图片描述
    Msqid_ds 维护消息队列的结构体,队列的第一个消息指针msg_first,最后一个消息指针msg_last
    消息中有一个成员指针next

每一个消息中包含有哪些内容:
Data 数据
Length 数据的长度
Type 数据的类型。
例如:
1----voltage data
2----电流数据
3----有功功率
消息的接收端可以根据消息的类型来接收。
在这里插入图片描述
(1) msgget
在这里插入图片描述

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
        int msgid;


        msgid =msgget(IPC_PRIVATE, 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

在这里插入图片描述
创建了消息队列
(2) msgsnd
在这里插入图片描述

msgctl(要删除的id号,要做说明操作,返回值);

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int msgid;


    msgid =msgget(IPC_PRIVATE, 0777);
    if(msgid <0)
    {
            printf("creat message queue failure\n");
            return -1;
    }
    printf("creat message queue sucess mid = %d\n",msgid);
    system("ipcs -q");

    msgctl(msgid,IPC_RMID,NULL);
    system("ipcs -q");
    //system("ipcrm -m shmid");
    return 0;
}

在这里插入图片描述
删除队列消息

(2) msgsnd发送消息
在这里插入图片描述

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        //定义消息的对象
        struct msgbuf sendbuf;


        msgid =msgget(IPC_PRIVATE, 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        //初始话消息
        sendbuf.type = 100;
        printf("please input message:\n");
        fgets(sendbuf.voltage,124,stdin);

        //开始写消息到消息队列
        msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
        system("ipcs -q");
        while(1);
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

在这里插入图片描述

(3) msgrcv接收函数
在这里插入图片描述

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        int readret;
        //定义消息的对象
        struct msgbuf sendbuf,recvbuf;


        msgid =msgget(IPC_PRIVATE, 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        //初始话消息
        sendbuf.type = 100;
        printf("please input message:\n");
        fgets(sendbuf.voltage,124,stdin);

        //开始写消息到消息队列
        msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
        //开始读消息到消息队列里
        memset(recvbuf.voltage,0,124);
        readret = msgrcv(msgid,(void *)&recvbuf,124,100,0);
        printf("recv =%s",recvbuf.voltage);
        printf("readret = %d\n",readret);
        system("ipcs -q");
        while(1);
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

在这里插入图片描述
消息队列中数据读后,数据也不存在了,再次读取的时候数据没有了

msgsnd和msgrcv都可以设置为阻塞方式和非阻塞方式,阻塞方式设置为0

例子:通过消息队列,设置A和B之间的无亲缘之间的通信,可以相互通信,不单只是单向通信
写的程序(单向)

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        int readret;
        int key;
        //定义消息的对象
        struct msgbuf sendbuf,recvbuf;
        key =ftok("./a.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -2;
        }
        printf("creat key sucess\n");

        msgid =msgget(key,IPC_CREAT | 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        sendbuf.type = 100;

        //写消息队列
        while(1)
        {
                //初始化缓存
                memset(sendbuf.voltage,0,124);
                //初始话消息
                //sendbuf.type = 100;
                printf("please input message:\n");
                fgets(sendbuf.voltage,124,stdin);

                //开始写消息到消息队列
                msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
                //开始读消息到消息队列里
                memset(recvbuf.voltage,0,124);
        }
        system("ipcs -q");
        while(1);
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

读的函数(单向)

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        int readret;
        int key;
        //定义消息的对象
        struct msgbuf sendbuf,recvbuf;
        key =ftok("./a.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -2;
        }
        printf("creat key sucess\n");

        msgid =msgget(key,IPC_CREAT | 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
       
        //开始读消息队列
        while(1)
        {
                //初始化读缓存
                memset(recvbuf.voltage,0,124);
                //开始读消息队列内容
                msgrcv(msgid,(void *)&recvbuf,124,100,0);
                printf("receive data from message queue:%s",recvbuf.voltage);
        }
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

在这里插入图片描述
证明可以单向通信

通过父子进程实现双向通信
在这里插入图片描述
服务器端的实现

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        int readret;
        int key;
        //定义消息的对象
        struct msgbuf sendbuf,recvbuf;
        int pid;
        key =ftok("./b.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -2;
        }
        printf("creat key sucess\n");

        msgid =msgget(key,IPC_CREAT | 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        pid = fork();
        if(pid > 0)//父进程写
        {

        sendbuf.type = 100;

        //写消息队列
        while(1)
        {
                //初始化缓存
                memset(sendbuf.voltage,0,124);
                //初始话消息
                //sendbuf.type = 100;
                printf("please input message:\n");
                fgets(sendbuf.voltage,124,stdin);

                //开始写消息到消息队列
                msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
                //开始读消息到消息队列里
                memset(recvbuf.voltage,0,124);
        }
        }
        if(pid  == 0)//子进程读
        {
                while(1)
                {
                memset(recvbuf.voltage,0,124);
                msgrcv(msgid,(void *)&recvbuf,124,200,0);//从哪里读,读到哪里去,读多少个,读什么样的数据类型,以什么方式读(0为阻塞)
                printf("receive message from message queue:%s\n",recvbuf.voltage);
                }
        }

        system("ipcs -q");
        while(1);
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

客户端的实现

#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
//消息队列的数据类型
struct msgbuf
{
        long type;
        char voltage[124];
        char ID[14];
};
int main()
{
        int msgid;
        int readret;
        int key;
        //定义消息的对象
        struct msgbuf sendbuf,recvbuf;
        int pid;
        key =ftok("./b.c",'a');
        if(key < 0)
        {
                printf("creat key failure\n");
                return -2;
        }
        printf("creat key sucess\n");

        msgid =msgget(key,IPC_CREAT | 0777);
        if(msgid <0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess mid = %d\n",msgid);
        system("ipcs -q");
        pid = fork();
        if(pid ==  0)//子进程写
        {

        sendbuf.type = 200;

        //写消息队列
        while(1)
        {
                //初始化缓存
                memset(sendbuf.voltage,0,124);
                //初始话消息
                //sendbuf.type = 100;
                printf("please input message:\n");
                fgets(sendbuf.voltage,124,stdin);

                //开始写消息到消息队列
                msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
                //开始读消息到消息队列里
                memset(recvbuf.voltage,0,124);
        }
        }
        if(pid > 0)//父进程读
        {
                while(1)
                {
                memset(recvbuf.voltage,0,124);
                msgrcv(msgid,(void *)&recvbuf,124,100,0);//从哪里读,读到哪里去,读多少个,读什么样的数据类型,以什么方式读(0为阻塞)
                printf("receive message from message queue:%s\n",recvbuf.voltage);
                }
        }
        system("ipcs -q");
        while(1);
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        //system("ipcrm -m shmid");
        return 0;
}

在这里插入图片描述
通过对队列消息的操作,对同一个文件b.c的读写利用fork产生的key属性,客户端和服务端都对key操作,父子进程交叉进程读写

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值