通过信号量和共享内存,实现不同进程间同步的收发收据

// 设计一个程序,作为进程A,
// 进程A专门创建一个信号量集,要求信号量集中有1个信号量,对信号量集合中的信号量进行设置,
// 要求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B和进程C,
// 要求进程B和进程C使用进程A创建的信号量集合中的信号量实现互斥访问。
// 提示:进程A、进程B、进程C需要使用共享内存作为临界资源的访问。

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/wait.h>
/********************************************************/
//优化前
// 定义一个联合体
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

// 初始化信号量
int init_sem(int sem_id, int init_value)
{
    union semun sem_union;
    sem_union.val = init_value;
    if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
    {
        perror("Initialize semaphore");
        return -1;
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    // 创建一个信号量集
    int sem_id = semget(ftok("./mysem", 1), 1, 0666 | IPC_CREAT);
    if (sem_id == -1)
    {
        perror("Create semaphore set");
        return -1;
    }
    // 初始化信号量
    if (init_sem(sem_id, 1) == -1)
    {
        return -1;
    }
    // 创建共享内存
    int shm_id = shmget(ftok("./myshm", 1), sizeof(int), 0666 | IPC_CREAT);
    if (shm_id == -1)
    {
        perror("Create shared memory");
        return -1;
    }
    // 将共享内存连接到当前进程的地址空间
    int *shmaddr = (int *)shmat(shm_id, NULL, 0);
    if (shmaddr == (int *)-1)
    {
        perror("Attach shared memory");
        return -1;
    }

    *shmaddr = 0; // 初始化共享内存中的变量

    // 创建进程B
    pid_t pid_b = fork();
    if (pid_b == 0)
    {
        // 子进程B
        struct sembuf sem_op;
        while (1)
        {
            // 等待信号量
            sem_op.sem_num = 0;
            sem_op.sem_op = -1;
            sem_op.sem_flg = SEM_UNDO;
            if (semop(sem_id, &sem_op, 1) == -1)
            {
                perror("semop wait");
                exit(1);
            }

            // 进入临界区
            (*shmaddr)++;
            printf("Process B: a = %d\n", *shmaddr);
            printf("Process B is accessing shared memory\n");
            sleep(1);

            // 释放信号量
            sem_op.sem_num = 0;
            sem_op.sem_op = 1;
            sem_op.sem_flg = SEM_UNDO;
            if (semop(sem_id, &sem_op, 1) == -1)
            {
                perror("semop signal");
                exit(1);
            }

            sleep(1);
        }
        exit(0);
    }
    else if (pid_b < 0)
    {
        perror("fork");
        return -1;
    }

    // 等待进程B完成第一次操作
    sleep(2);

    // 创建进程C
    pid_t pid_c = fork();
    if (pid_c == 0)
    {
        // 子进程C
        struct sembuf sem_op;
        while (1)
        {
            // 等待信号量
            sem_op.sem_num = 0;
            sem_op.sem_op = -1;
            sem_op.sem_flg = SEM_UNDO;
            if (semop(sem_id, &sem_op, 1) == -1)
            {
                perror("semop wait");
                exit(1);
            }

            // 进入临界区
            printf("Process C: a = %d\n", *shmaddr);
            printf("Process C is accessing shared memory\n");
            sleep(1);

            // 释放信号量
            sem_op.sem_num = 0;
            sem_op.sem_op = 1;
            sem_op.sem_flg = SEM_UNDO;
            if (semop(sem_id, &sem_op, 1) == -1)
            {
                perror("semop signal");
                exit(1);
            }

            sleep(1);
        }
        exit(0);
    }
    else if (pid_c < 0)
    {
        perror("fork");
        return -1;
    }

    // 等待进程B和进程C结束
    waitpid(pid_b, NULL, 0);
    waitpid(pid_c, NULL, 0);

    // 断开共享内存
    if (shmdt(shmaddr) == -1)
    {
        perror("shmdt error");
        exit(-1);
    }

    // 删除共享内存
    shmctl(shm_id, IPC_RMID, 0);
    // 删除信号量集合
    semctl(sem_id, 0, IPC_RMID);

    return 0;
}
/**********************************************/



void process_task(int sem_id, int *shmaddr, const char *process_name)
{
    struct sembuf sem_op;

    while (1)
    {
        // 等待信号量
        sem_op.sem_num = 0;
        sem_op.sem_op = -1;
        sem_op.sem_flg = SEM_UNDO;
        if (semop(sem_id, &sem_op, 1) == -1)
        {
            perror("semop wait");
            exit(1);
        }

        // 进入临界区
        if (strcmp(process_name, "Process B") == 0)
        {
            (*shmaddr)++;
            printf("%s: a = %d\n", process_name, *shmaddr);
        }

        printf(" 进程 %s \n", process_name);

        sleep(1);

        // 释放信号量
        sem_op.sem_num = 0;
        sem_op.sem_op = 1;
        sem_op.sem_flg = SEM_UNDO;
        if (semop(sem_id, &sem_op, 1) == -1)
        {
            perror("semop signal");
            exit(1);
        }

        sleep(1);
    }
}

int main(int argc, char const *argv[])
{
    // 创建一个信号量集
    int sem_id = semget(ftok("./mysem", 1), 1, 0666 | IPC_CREAT);
    if (sem_id == -1)
    {
        perror("Create semaphore set");
        return -1;
    }
    // 初始化信号量
    if (init_sem(sem_id, 1) == -1)
    {
        return -1;
    }
    // 创建共享内存
    int shm_id = shmget(ftok("./myshm", 1), sizeof(int), 0666 | IPC_CREAT);
    if (shm_id == -1)
    {
        perror("Create shared memory");
        return -1;
    }
    // 将共享内存连接到当前进程的地址空间
    int *shmaddr = (int *)shmat(shm_id, NULL, 0);
    if (shmaddr == (int *)-1)
    {
        perror("Attach shared memory");
        return -1;
    }

    *shmaddr = 0; // 初始化共享内存中的变量

    // 创建进程B
    pid_t pid_b = fork();
    if (pid_b == 0)
    {
        // 子进程B
        process_task(sem_id, shmaddr, "Process B");
        exit(0);
    }
    else if (pid_b < 0)
    {
        perror("fork");
        return -1;
    }

    // 创建进程C
    pid_t pid_c = fork();
    if (pid_c == 0)
    {
        // 子进程C
        process_task(sem_id, shmaddr, "Process C");
        printf("进程C中数值不变 %d\n", *shmaddr);
        exit(0);
    }
    else if (pid_c < 0)
    {
        perror("fork");
        return -1;
    }

    // 等待进程B和进程C结束
    waitpid(pid_b, NULL, 0);
    waitpid(pid_c, NULL, 0);

    // 断开共享内存
    if (shmdt(shmaddr) == -1)
    {
        perror("shmdt error");
        exit(-1);
    }

    // 删除共享内存
    shmctl(shm_id, IPC_RMID, 0);
    // 删除信号量集合
    semctl(sem_id, 0, IPC_RMID);

    return 0;
}

posted @ 2024-05-28 19:33  晖_IL  阅读(17)  评论(2编辑  收藏  举报