共享内存练习题

设计三个程序,要求三个程序申请一块共享内存,并分别映射到各自进程的地址空间,进程A和进程B对共享内存段中的数据进行修改,然后进程C不断输出共享内存段中的数据,并观察效果,要求实现进程间的互斥,避免竞争。

进程A:

/*******************************************************************
 *
 *	file name:	A.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *	function :  进程A,用于对共享内存中的数据进行修改
 * 	note	 :  None
 *
 *	CopyRight (c)  2024  Dazz_24@163.com   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>

char *p;

// 进程A收到信号会对共享内存段中的数据进行修改
void sighandler(int a)
{
    sprintf(p, "Hello,here is processA\n");
}

int main()
{
    // 打开共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 512, 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), 512, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }
    }

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

    // 打印自己的PID
    printf("the PID of processA is %d\n", getpid());

    // 等待接收SIGUSR1的信号
    signal(SIGUSR1, sighandler);

    while (1);

    // 销毁链接得到的虚拟地址
    shmdt(p);

    return 0;
}

进程B:

/*******************************************************************
 *
 *	file name:	B.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *	function :  进程B,用于对共享内存中的数据进行修改
 * 	note	 :  None
 *
 *	CopyRight (c)  2024  Dazz_24@163.com   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>

char *p;

// 进程A收到信号会对共享内存段中的数据进行修改
void sighandler(int a)
{
    sprintf(p, "Hi,here is processB\n");
}

int main()
{
    // 打开共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 512, 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), 512, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }
    }

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

    // 等待接收SIGUSR2的信号
    signal(SIGUSR2, sighandler);

    // 打印自己的PID
    printf("the PID of processA is %d\n", getpid());

    while (1);

    // 销毁链接得到的虚拟地址
    shmdt(p);

    return 0;
}

进程C:

/*******************************************************************
 *
 *	file name:	C.c
 *	author	 :  Dazz
 *	date	 :  2024/05/28
 *	function :  进程C,用于读取并输出对共享内存中的数据
 * 	note	 :  None
 *
 *	CopyRight (c)  2024  Dazz_24@163.com   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 <signal.h>
#include <unistd.h>

int main()
{
    // 打开共享内存段,如果不存在则创建,如果存在则打开
    int shm_id = shmget(ftok("..", 76), 512, 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), 512, 0644);
        if (-1 == shm_id)
        {
            // 如打开失败则直接退出程序
            fprintf(stderr, "shmget fail!,error: %d, %s\n", errno, strerror(errno));
            exit(1);
        }
    }

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

    // 手动输入进程A和进程B的pid
    int PidA, PidB;
    printf("please input the PID of processA\n");
    scanf("%d", &PidA);

    printf("please input the PID of processB\n");
    scanf("%d", &PidB);

    while (1)
    {
        // 给进程A发送信号
        kill(PidA, SIGUSR1);

        sleep(2);

        // 输出读到的数据
        printf("%s\n", p);

        // 给进程B发送信号
        kill(PidB, SIGUSR2);

        sleep(2);

        // 输出读到的数据
        printf("%s\n", p);
    }
    // 销毁链接得到的虚拟地址
    shmdt(p);

    return 0;
}
posted @ 2024-05-28 13:25  Dazz_24  阅读(30)  评论(0)    收藏  举报