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

文章讲述了如何使用消息队列和共享内存以及信号量集在两个进程(A和B)间进行对话,包括发送和接收消息,以及在共享内存中实现字符串的翻转输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息队列实现AB进程对话

要求

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

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

要求

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

code如下:

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

send_msg.c

#include <my_head.h>

//  消息包格式
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;
}

rcv_msg.c

#include <my_head.h>

//  消息包格式
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;
}

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

print.c

#include <my_head.h>

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;
}

swap.c

#include <my_head.h>

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhk___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值