• 消息队列实现AB进程对话;共享内存和信号量集完成多进程字符串翻转与输出


    消息队列实现AB进程对话

    要求

    • A进程先发送一句话给B进程,B进程接收后打印
    • B进程再回复一句话给A进程,A进程接收后打印
    • 重复1.2步骤

    共享内存和信号量集完成多进程字符串翻转与输出

    要求

    • 在共享内存中存入字符串 “1234567”。
    • A进程循环打印字符串,B进程循环倒置字符串,
    • 结果不允许出现乱序:
    • 两种顺序交替输出

    code如下:

    消息队列实现AB进程对话代码

    send_msg.c

    #include 
    
    //  消息包格式
    typedef struct msgbuff
    {
        long mtype;     //  消息类型,必须大于0
        char data[128]; //  消息内容
    } msg;
    
    int main(int argc, const char *argv[])
    {
        //  创建一个Key1
        key_t key1 = ftok("/home/ubuntu/", 1);
        if (key1 < 0)
        {
            ERR_MSG("ftok");
            return -1;
        }
    
        //  创建一个Key2
        // key_t key2 = ftok("/home/ubuntu/", 2);
        // if (key2 < 0)
        // {
        //     ERR_MSG("ftok");
        //     return -1;
        // }
    
        printf("key1 = %#x\n", key1);
        // printf("key2 = %#x\n", key2);
    
        //  根据key1创建一个消息队列
        int msqid1 = msgget(key1, IPC_CREAT | 0664);
        if (msqid1 < 0)
        {
            ERR_MSG("msgget");
            return -1;
        }
        //  根据key2创建一个消息队列
        // int msqid2 = msgget(key2, IPC_CREAT | 0664);
        // if (msqid2 < 0)
        // {
        //     ERR_MSG("msgget");
        //     return -1;
        // }
    
        printf("msqid1 = %d\n", msqid1);
        // printf("msqid2 = %d\n", msqid2);
    
        msg buff1;
        // msg buff2;
        ssize_t res = 0;
        while (1)
        {
            //  获取消息
            printf("请输入消息类型:");
            scanf("%ld", &buff1.mtype);
            //  吸收垃圾字符,如数字后面的换行或空格之类
            getchar();
            //  退出条件
            if (0 == buff1.mtype)
            {
                break;
            }
    
            printf("请输入消息内容:");
            fgets(buff1.data, sizeof(buff1.data), stdin);
            buff1.data[strlen(buff1.data) - 1] = 0;
    
            //  以阻塞方式发送
            if (msgsnd(msqid1, (void *)&buff1, sizeof(buff1.data), 0) < 0)
            {
                ERR_MSG("msgsend");
                return -1;
            }
            printf("发送成功\n");
    
            res = msgrcv(msqid1, &buff1, sizeof(buff1), 2, 0);
            if (res < 0)
            {
                ERR_MSG("msgrcv");
                break;
            }
    
            printf("res = %ld 类型:%4ld 内容:%s\n", res, buff1.mtype, buff1.data);
        }
    
        //  使用shell命令查看消息队列
        system("ipcs -q");
        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

    rcv_msg.c

    #include 
    
    //  消息包格式
    typedef struct msgbuff
    {
        long mtype;     //  消息类型,必须大于0
        char data[128]; //  消息内容
    } msg;
    
    int main(int argc, const char *argv[])
    {
        //  创建一个Key
        key_t key1 = ftok("/home/ubuntu/", 1);
        if (key1 < 0)
        {
            ERR_MSG("ftok");
            return -1;
        }
        printf("key1 = %#x\n", key1);
    
        //  根据key创建一个消息队列
        int msqid1 = msgget(key1, IPC_CREAT | 0664);
        if (msqid1 < 0)
        {
            ERR_MSG("msgget");
            return -1;
        }
    
        printf("msqid1 = %d\n", msqid1);
    
        msg buff1;
        ssize_t res = 0;
        while (1)
        {
            //  获取消息
            printf("请输入消息类型:");
            scanf("%ld", &buff1.mtype);
            //  吸收垃圾字符,如数字后面的换行或空格之类
            getchar();
            //  退出条件
            if (0 == buff1.mtype)
            {
                break;
            }
    
            printf("请输入消息内容:");
            fgets(buff1.data, sizeof(buff1.data), stdin);
            buff1.data[strlen(buff1.data) - 1] = 0;
    
            //  以阻塞方式发送
            if (msgsnd(msqid1, (void *)&buff1, sizeof(buff1.data), 0) < 0)
            {
                ERR_MSG("msgsend");
                return -1;
            }
            printf("发送成功\n");
    
            res = msgrcv(msqid1, &buff1, sizeof(buff1), 1, 0);
            if (res < 0)
            {
                ERR_MSG("msgrcv");
                break;
            }
    
            printf("res = %ld 类型:%4ld 内容:%s\n", res, buff1.mtype, buff1.data);
        }
    
        //  使用shell命令查看消息队列
        system("ipcs -q");
        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

    共享内存和信号量集完成多进程字符串翻转与输出代码

    print.c

    #include 
    
    int main(int argc, const char *argv[])
    {
        //  创建key
        key_t key = ftok("./", 2);
        if (key < 0)
        {
            ERR_MSG("ftok");
            return -1;
        }
        //  根据key创建共享内存
        int shmid = shmget(key, 8, IPC_CREAT | 0664);
        if (shmid < 0)
        {
            ERR_MSG("shmget");
            return -1;
        }
        //  将共享内存映射到用户空间
        void *addr = shmat(shmid, NULL, 0);
        if ((void *)-1 == addr)
        {
            ERR_MSG("shmat");
            return -1;
        }
        //  向共享内存中填充数据
        strcpy((char *)addr, "1234567");
    
        //  根据key创建信号灯集
        int semid = semget(key, 2, IPC_CREAT | 0664);
        if (semid < 0)
        {
            ERR_MSG("semget");
            return -1;
        }
    
        //  setall
        unsigned short setall[2] = {1, 0};
        if (semctl(semid, 0, SETALL, setall))
        {
            ERR_MSG("semctl");
            return -1;
        }
    
        //  初始化信号灯
        struct sembuf sops;
        sops.sem_num = 0; //  对0号灯操作
        sops.sem_op = 0;  //  wait for zero操作
        sops.sem_flg = 0; //  阻塞方式运行
    
        int i = 0;
        //  输出
        while (i < 90)
        {
            //  P 操作 0号
            sops.sem_num = 0;
            sops.sem_op = -1;
            if (semop(semid, &sops, 1) < 0)
            {
                ERR_MSG("semop");
                return -1;
            }
    
            printf("%s\n", (char *)addr);
    
            //  V 操作 1号
            sops.sem_num = 1;
            sops.sem_op = 1;
            if (semop(semid, &sops, 1) < 0)
            {
                ERR_MSG("semop");
                return -1;
            }
            i++;
        }
    
        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

    swap.c

    #include 
    
    int main(int argc, const char *argv[])
    {
        //  创建key
        key_t key = ftok("./", 2);
        if (key < 0)
        {
            ERR_MSG("ftok");
            return -1;
        }
        //  根据key创建共享内存
        int shmid = shmget(key, 8, IPC_CREAT | 0664);
        if (shmid < 0)
        {
            ERR_MSG("shmget");
            return -1;
        }
        //  将共享内存映射到用户空间
        void *addr = shmat(shmid, NULL, 0);
        if ((void *)-1 == addr)
        {
            ERR_MSG("shmat");
            return -1;
        }
    
        //  根据key创建信号灯集
        int semid = semget(key, 2, IPC_CREAT | 0664);
        if (semid < 0)
        {
            ERR_MSG("semget");
            return -1;
        }
    
        //  setall
        unsigned short setall[2] = {1, 0};
        if (semctl(semid, 0, SETALL, setall))
        {
            ERR_MSG("semctl");
            return -1;
        }
        
        //  初始化信号灯
        struct sembuf sops;
        sops.sem_num = 0; //  对0号灯操作
        sops.sem_op = 0;  //  wait for zero操作
        sops.sem_flg = 0; //  阻塞方式运行
    
        char temp = 0;
        char *start = NULL, *end = NULL;
    
        while (1)
        {
            //  P 操作 1号
            sops.sem_num = 1;
            sops.sem_op = -1;
            if (semop(semid, &sops, 1) < 0)
            {
                ERR_MSG("semop");
                return -1;
            }
    
            //  逆置
            start = (char *)addr;
            end = start + strlen(start) - 1;
            while (start < end)
            {
                temp = *start;
                *start = *end;
                *end = temp;
                start++;
                end--;
            }
    
            // sleep(1);
            //  V 操作 1号
            sops.sem_num = 0;
            sops.sem_op = 1;
            if (semop(semid, &sops, 1) < 0)
            {
                ERR_MSG("semop");
                return -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
  • 相关阅读:
    VS Code使用clang-format自定义C++代码默认格式化样式
    图像相似度对比方法
    CSS之字体和层叠样式表引入
    网安学习-Python安全开发
    华为手机隐藏的这个功能,简直是办公旅人爱用好物
    WPF知识小结(2)
    Activity中何时能拿到组件的宽高
    ps显示msvcp140.dll丢失的解决方法,四个解决方法分享
    SpringBoot SpringBoot 原理篇 3 核心原理 3.5 启动流程【4】【5】【6】
    抓包后使用postman访问出错,后端报错 MalformedJsonException: Unterminated string
  • 原文地址:https://blog.csdn.net/qq_52625576/article/details/132891409