首页 > 系统相关 >共享内存练习题

共享内存练习题

时间:2024-05-28 21:12:56浏览次数:29  
标签:练习题 共享内存 errno 信号量 进程 sem include id

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

程序A

/*******************************************************************
 *
 *	file name:	semA.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *
 *  function :  进程A,进程A专门创建一个信号量集,要求信号量集中有1个信
 *              号量,对信号量集合中的信号量进行设置,要求集合中的信号量
 *              的初值为1
 *
 *  note	 :  设计一个程序,作为进程A,进程A专门创建一个信号量集,要求
 *              信号量集中有1个信号量,对信号量集合中的信号量进行设置,要
 *              求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B
 *              和进程C,要求进程B和进程C使 用进程A创建的信号量集合中的信
 *              号量实现互斥访问。  提示:进程A、进程B、进程C需要使用共享
 *              内存作为临界资源的访问。
 *
 *	CopyRight (c)  2024  [email protected]   All Right Reseverd
 *
 * *****************************************************************/

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <signal.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun
{
    int val;               /* Value for SETVAL */
    struct semid_ds *buf;  /* Buffer for IPC_STAT, IPC_SET */
    unsigned short *array; /* Array for GETALL, SETALL */
    struct seminfo *__buf; /* Buffer for IPC_INFO
                              (Linux-specific) */
};

int main()
{
    // 创建信号量级,如果不存在则创建,如果存在则打开
    int sem_id = semget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == sem_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        sem_id = semget(ftok("..", 76), 1, 0644);
        if (-1 == sem_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }

        // 创建管理信号量级的联合体
        union semun sem_ctl;

        // 对信号量值进行赋值
        sem_ctl.val = 1;

        // 定义一个变量来接收semctl的返回值
        int semstl_rev;

        // 用semctl对信号量值进行赋值
        if ((semstl_rev = semctl(sem_id, 0, SETVAL, sem_ctl) == -1))
        {
            // 如果存在则会报错
            fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(2);
        }
    }

    // 创建共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == shm_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        shm_id = shmget(ftok("..", 76), 4, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(3);
        }
    }

    // 设置信号量并初始化
    struct sembuf sops;
    sops.sem_num = 0; // 信号量集中的信号量元素的下标
    sops.sem_op = 1;  // P\V操作
    sops.sem_flg = 0; // 默认

    // 使用semop函数对信号量集进行操作
    if (semop(sem_id, &sops, 1) == -1)
    {
        fprintf(stderr, "shmget error, errno: %d, %s\n", errno, strerror(errno));
        exit(4);
    }

    // 把共享内存段连接到进程空间
    int *p = (int *)shmat(shm_id, NULL, 0);
    if ((void *)-1 == p)
    {
        // 如连接失败则直接退出程序
        fprintf(stderr, "shmat fail!,error: %d, %s\n", errno, strerror(errno));
        exit(5);
    }

    // 把一个整数存储到共享内存里
    *p = 0;

    return 0;
}

进程B

/*******************************************************************
 *
 *	file name:	semB.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *
 *  function :  进程B,进程B和进程C使用进程A创建的信号量集合中的信号量
 *              实现互斥访问。
 *
 *  note	 :  设计一个程序,作为进程A,进程A专门创建一个信号量集,要求
 *              信号量集中有1个信号量,对信号量集合中的信号量进行设置,要
 *              求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B
 *              和进程C,要求进程B和进程C使 用进程A创建的信号量集合中的信
 *              号量实现互斥访问。  提示:进程A、进程B、进程C需要使用共享
 *              内存作为临界资源的访问。
 *
 *	CopyRight (c)  2024  [email protected]   All Right Reseverd
 *
 * *****************************************************************/

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

/******************************************************
 *
 *  name      : P
 *	function  : 实现P操作
 *  argument
 *              @sops    :结构体的地址
 *              @sem_id  :共享内存的标识符
 *
 *  retval    : void
 *  author    : Dazz
 *  date      : 2024/5/28
 *  note      : None
 *
 * *******************************************************/
void P(struct sembuf *sops, int sem_id)
{
    sops->sem_op = -1;
    if ((semop(sem_id, sops, 1)) == -1)
    {
        printf("111\n");
        fprintf(stderr, "semop error, errno: %d, %s\n", errno, strerror(errno));
        exit(3);
        printf("22222\n");
    }
}

/******************************************************
 *
 *  name      : V
 *	function  : 实现V操作
 *  argument
 *              @sops    :结构体的地址
 *              @sem_id  :共享内存的标识符
 *
 *  retval    : void
 *  author    : Dazz
 *  date      : 2024/5/28
 *  note      : None
 *
 * *******************************************************/
void V(struct sembuf *sops, int sem_id)
{
    sops->sem_op = 1;
    if ((semop(sem_id, sops, 1)) == -1)
    {
        fprintf(stderr, "semop error, errno: %d, %s\n", errno, strerror(errno));
        exit(4);
    }
}

int main()
{

    // 打开共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == shm_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        shm_id = shmget(ftok("..", 76), 4, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }
    }
    // 把共享内存段连接到进程空间
    int *p = (int *)shmat(shm_id, NULL, 0);
    if ((void *)-1 == p)
    {
        // 如连接失败则直接退出程序
        fprintf(stderr, "shmat fail!,error: %d, %s\n", errno, strerror(errno));
        exit(2);
    }

    // 打开信号量级
    int sem_id = semget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == sem_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        sem_id = semget(ftok("..", 76), 1, 0644);
        if (-1 == sem_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }

        // 对结构体进行初始化
        struct sembuf sops;
        memset(&sops, 0, sizeof(sops));

        while (1)
        {
            // P操作
            P(&sops, sem_id);

            // 修改共享内存里的数据
            (*p)++;

            sleep(2);

            // V操作
            V(&sops, sem_id);
        }

        return 0;
    }
}

进程C

/*******************************************************************
 *
 *	file name:	semB.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *
 *  function :  进程C,进程B和进程C使用进程A创建的信号量集合中的信号量
 *              实现互斥访问。
 *
 *  note	 :  设计一个程序,作为进程A,进程A专门创建一个信号量集,要求
 *              信号量集中有1个信号量,对信号量集合中的信号量进行设置,要
 *              求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B
 *              和进程C,要求进程B和进程C使 用进程A创建的信号量集合中的信
 *              号量实现互斥访问。  提示:进程A、进程B、进程C需要使用共享
 *              内存作为临界资源的访问。
 *
 *	CopyRight (c)  2024  [email protected]   All Right Reseverd
 *
 * *****************************************************************/

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

struct sembuf sops;

/******************************************************
 *
 *  name      : P
 *	function  : 实现P操作
 *  argument
 *              @sem_id  :共享内存的标识符
 *
 *  retval    : void
 *  author    : Dazz
 *  date      : 2024/5/28
 *  note      : None
 *
 * *******************************************************/
void P(int sem_id)
{
    sops.sem_op = -1;
    if (semop(sem_id, &sops, 1) == -1)
    {
        fprintf(stderr, "semop error, errno: %d, %s\n", errno, strerror(errno));
        exit(3);
    }
}

/******************************************************
 *
 *  name      : V
 *	function  : 实现V操作
 *  argument
 *              @sem_id  :共享内存的标识符
 *
 *  retval    : void
 *  author    : Dazz
 *  date      : 2024/5/28
 *  note      : None
 *
 * *******************************************************/
void V(int sem_id)
{
    sops.sem_op = 1;
    if (semop(sem_id, &sops, 1) == -1)
    {
        fprintf(stderr, "shmget error, errno: %d, %s\n", errno, strerror(errno));
        exit(4);
    }
}

int main()
{

    // 打开共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == shm_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        shm_id = shmget(ftok("..", 76), 4, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }
    }

    // 把共享内存段连接到进程空间
    int *p = (int *)shmat(shm_id, NULL, 0);
    if ((void *)-1 == p)
    {
        // 如连接失败则直接退出程序
        fprintf(stderr, "shmat fail!,error: %d, %s\n", errno, strerror(errno));
        exit(2);
    }

    // 打开信号量级
    int sem_id = semget(ftok("..", 76), 1, IPC_CREAT | IPC_EXCL | 0644);
    if (-1 == sem_id)
    {
        // 如果存在则会报错
        fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));

        // 如存在,则打开共享内存段即可
        sem_id = semget(ftok("..", 76), 1, 0644);
        if (-1 == sem_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "semget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }

        // 对结构体进行初始化
        memset(&sops, 0, sizeof(sops));

        while (1)
        {
            // P操作
            P(sem_id);

            // 修改共享内存里的数据
            printf("this is what I read from shm:%d\n", *p);

            sleep(2);
            // V操作
            V(sem_id);
        }

        return 0;
    }
}

标签:练习题,共享内存,errno,信号量,进程,sem,include,id
From: https://www.cnblogs.com/Dazz24/p/18218902

相关文章

  • iceoryx源码阅读(四)——共享内存通信(二)
    目录1 队列数据结构2 共享内存获取2.1 PublisherImpl::loan2.2PublisherImpl::loanSample2.3 PublisherPortUser::tryAllocateChunk2.4ChunkSender::tryAllocate3 消息发送逻辑3.1PublisherImpl::publish3.2PublisherPortUser::sendChunk3.3ChunkSender::send3.4ChunkDistri......
  • 系统编程练习题---利用共享内存和信号量集,完成两个进程之间的互斥通信
    目录题目解析代码展示process_A.cprocess_B.cprocess_C.c结果展示重要知识点记录题目设计一个程序,作为进程A,进程A专门创建一个信号量集,要求信号量集中有1个信号量,对信号量集合中的信号量进行设置,要求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B和进程C,要求进程B和进程......
  • 信号量集与共享内存
    信号量集与共享内存​ 今日练习:设计一个程序,作为进程A,进程A专门创建一个信号量集,要求信号量集中有1个信号量,对信号量集合中的信号量进行设置,要求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B和进程C,要求进程B和进程C使用进程A创建的信号量集合中的信号量实现互斥访问。......
  • A申请共享内存并对信号量进行初始化,然后进程B与C实现互斥
    练习:设计一个程序,作为进程A,进程A专门创建一个信号量集,要求信号量集中有1个信号量,对信号量集合中的信号量进行设置,要求集合中的信号量的初值为1,然后再设计2个程序,分别是进程B和进程C,要求进程B和进程C使用进程A创建的信号量集合中的信号量实现互斥访问。提示:进程A、进程B、进......
  • 9. 子查询练习题
    1.查询和Zlotkey相同部门的员工姓名和工资selectfirst_name,last_name,salaryfromemployeesewheredepartment_id=(selectdepartment_id fromemployeese2 wherelast_name='Zlotkey' );2.查询工资比公司平均工资高的员工的员工号,姓名和工......
  • 共享内存练习题
    设计三个程序,要求三个程序申请一块共享内存,并分别映射到各自进程的地址空间,进程A和进程B对共享内存段中的数据进行修改,然后进程C不断输出共享内存段中的数据,并观察效果,要求实现进程间的互斥,避免竞争。进程A:/******************************************************************......
  • 消息队列练习题
    消息队列练习题进程A/**********************************************************************filename:mesqa.c*author:[email protected]*date:2024/5/28*function:接收进程b的信号,读出消......
  • 消息队列练习题
    题目:要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并把进程的PID作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。进程A的代码://构造用于接收消息......
  • 系统编程练习题----使用消息队列实现两个进程之间的通信
    目录题目思路代码展示进程A进程B结果展示题目要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并写入一段信息作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文......
  • 8. 聚合函数练习题
    【题目】1.where子句可否使用组函数进行过滤?selectmax(salary),min(salary),avg(salary),sum(salary)fromemployeese;2.查询公司员工工资的最大值,最小值,平均值,总和selectmax(salary),min(salary),avg(salary),sum(salary)fromemployeesegroupbyjob_i......