消息队列实现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;
}

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

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

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

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

你可能感兴趣的:(c++,c语言,linux,服务器)