• 嵌入式Linux C进程间通信(三)——消息队列


    前述

    System V IPC
    在这里插入图片描述
    特点:
    与管道有所不同,它完全使用了不同的实现机制,与文件没任何的关系,也就是说内核不再以文件的形式来管理System V IPC
    System V IPC不再以文件的形式存在,因此没有文件描述符这个东西,但是它有类似的“标识符”
    任何进程之间通信时,都可以使用System V IPC来通信
    POSIX也可以支持消息队列、共享内存、信号量能在unix下运行

    一、消息队列的创建和删除

    消息队列的本质就是由内核创建的用于存放消息的链表,由于是存放消息的,所以我们就把这个链表称为消息队列。

    1.1 消息的组成

    1. 消息编号:识别信息用
    2. 消息正文:真正的信息内容
      在这里插入图片描述

    1.2 创建

    int msgget(key_t key, int msgflg);
    在这里插入图片描述

    使用ftok生成key值
    在这里插入图片描述
    在这里插入图片描述

    1.2 查看系统的消息队列

    在这里插入图片描述
    在这里插入图片描述

    1.3 消息队列的创建

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSGNAME "./msg_file"
    
    int main(int argc, char const *argv[])
    {
        key_t key;
        int msgid;
    
        key = ftok(MSGNAME, 'k');
    
        msgid = msgget(key, IPC_CREAT | 0655);
        if (msgid < 0)
        {
            perror("msgid error!");
            exit(1);
        }
        printf("msgid = %d\n",msgid);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    1.4 获取属性及删除

    进程结束时,system v ipc不会自动删除,进程结束后,使用ipcs依然能够查看到

    长方形
    重启OS
    使用ipcrm命令删除
    int msgctl 参数:int mspid,int cmd,struct mspid_ds *buf
    ipcrm -Q msgkey移除用msqkey创建的消息队列
    ipcrm -q msqid移除用msqid标识的消息队列

    在这里插入图片描述
    msgctl
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSGNAME "./msg_file"
    
    int main(int argc, char const *argv[])
    {
        key_t key;
        int msgid;
    
        key = ftok(MSGNAME, 'k');
    
        msgid = msgget(key, IPC_CREAT | 0655);
        if (msgid < 0)
        {
            perror("msgid error!");
            exit(1);
        }
        printf("key = %x\n", key);
        printf("msgid = %d\n", msgid);
    
        msgctl(msgid,IPC_RMID,NULL);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    二、消息队列的发送和接收

    2.1 发送

    int msgsnd(int msqid,const void *msgp, size_t msgsz,int msgflg);
    在这里插入图片描述

    2.2 接收

    ssize_ t msgrcv(int msqid, void *msgp, size_ t msgsz, long msgtyp, int msgflg);
    在这里插入图片描述

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSGNAME "./msg_file"
    
    int msgid;
    
    struct msgbuf
    {
        long mtype;
        char mtext[1024];
    };
    
    void my_exit(int msg)
    {
        msgctl(msgid,IPC_RMID,NULL);
    }
    
    int main(int argc, char const *argv[])
    {
        key_t key;
        pid_t pid;
        signal(SIGINT, my_exit);
    
        key = ftok(MSGNAME, 'k');
    
        msgid = msgget(key, IPC_CREAT | 0655);
    
        if (msgid < 0)
        {
            perror("msgid error!");
            exit(1);
        }
        printf("key = %x\n", key);
        printf("msgid = %d\n", msgid);
    
        pid = fork();
        if (pid < 0)
        {
            perror("fork perror!\n");
            exit(1);
        }
        if (pid == 0)
        {
            long mtype;
            char buffer[1024];
            struct msgbuf pmsgbuf;
            while (1)
            {
                memset(buffer, 0, sizeof(buffer));
                memset(&pmsgbuf, 0, sizeof(struct msgbuf));
                printf("Please input send msg:\n");
                scanf("%s", buffer);
                strcpy(pmsgbuf.mtext, buffer);
                printf("Please input send msg id:\n");
                scanf("%ld", &mtype);
                pmsgbuf.mtype = mtype;
    
                if(msgsnd(msgid,(void *)&pmsgbuf,sizeof(pmsgbuf),IPC_NOWAIT) < 0)
                {
                    perror("msg snd error!");
                    exit(1);
                }
            }
        }
        else if(pid > 0)
        {
            size_t size;
            long mtype;
            char buffer[1024];
            struct msgbuf pmsgbuf;
            while (1)
            {
                memset(buffer, 0, sizeof(buffer));
                memset(&pmsgbuf, 0, sizeof(struct msgbuf));
                size = msgrcv(msgid, &pmsgbuf,sizeof(pmsgbuf),3,0);
    
                if (size < 0)
                {
                    perror("msg rcv error!");
                    exit(1);
                }
                printf("recv data:%s\n", pmsgbuf.mtext);
                sleep(1);
            }
        }
        
    
        
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    在这里插入图片描述

    三、任意进程通信及特点

    多个进程是如何共享到同一个消息队列?

    1. fork前创建
    2. 创建者把ID保存到某文件,共享进程读出ID即可+
    3. 使用ftok函数,利用与创建者相同的“路径名”和8位整形数,生成相同的key值

    消息队列的特点

    1. 传送有格式的消息流
    2. 多进程网状旁叉通信时,消息队列是上上之选
    3. 能实现大规模数据的通信

    3.1 msg_read.c

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSGNAME "./msg_file"
    
    struct msgbuf
    {
        long mtype;
        char mtext[1024];
    };
    
    
    int main(int argc, char const *argv[])
    {
        key_t key;
    
        key = ftok(MSGNAME, 'k');
    
        int msgid = msgget(key, IPC_CREAT | 0777);
    
        if (msgid < 0)
        {
            perror("msgid error!");
            exit(1);
        }
        printf("key = %x\n", key);
        printf("msgid = %d\n", msgid);
        size_t size;
        long mtype;
        char buffer[1024];
        struct msgbuf pmsgbuf;
        while (1)
        {
            memset(buffer, 0, sizeof(buffer));
            memset(&pmsgbuf, 0, sizeof(struct msgbuf));
            size = msgrcv(msgid, &pmsgbuf,sizeof(pmsgbuf),3,0);
    
            if (size < 0)
            {
                perror("msg rcv error!");
                exit(1);
            }
            printf("recv data:%s\n", pmsgbuf.mtext);
            sleep(1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    3.2 msg_write.c

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSGNAME "./msg_file"
    
    struct msgbuf
    {
        long mtype;
        char mtext[1024];
    };
    
    
    int main(int argc, char const *argv[])
    {
        key_t key;
    
        key = ftok(MSGNAME, 'k');
    
        int msgid = msgget(key, 0777 | IPC_CREAT);
    
        if (msgid < 0)
        {
            perror("msgid error!");
            exit(1);
        }
        printf("key = %x\n", key);
        printf("msgid = %d\n", msgid);
        size_t size;
        long mtype;
        char buffer[1024];
        struct msgbuf pmsgbuf;
        while (1)
        {
            memset(buffer, 0, sizeof(buffer));
            memset(&pmsgbuf, 0, sizeof(struct msgbuf));
            printf("Please input send msg:\n");
            scanf("%s", buffer);
            strcpy(pmsgbuf.mtext, buffer);
            printf("Please input send msg id:\n");
            scanf("%ld", &mtype);
            pmsgbuf.mtype = mtype;
    
            if(msgsnd(msgid,(void *)&pmsgbuf,sizeof(pmsgbuf),IPC_NOWAIT) < 0)
            {
                perror("msg snd error!");
                exit(1);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3.3 成果展示

    请添加图片描述

  • 相关阅读:
    用python写MapReduce函数——以WordCount为例
    【Java分享客栈】从线上环境摘取了四个代码优化记录分享给大家
    基于STM32单片机的智能窗帘系统
    3、Native方法区
    【uniapp】小程序开发7:自定义组件、自动注册组件
    QT 客户端软件开发
    Linux下设备树、pinctrl和gpio子系统、LED灯驱动实验
    12.Java 技术栈中间件优雅停机方案设计与实现全景图
    【论文笔记】Enabling technologies and tools for digital twin
    prometheus + grafana + node_exporter 搭建监控服务
  • 原文地址:https://blog.csdn.net/m0_52592798/article/details/126218051