实验六 进程间通信——共享内存

一、实验目的

1、了解采用共享内存通信的原理;

2、掌握共享内存的创建及使用方法。

二、实验内容

1、创建写进程,其功能为创建共享内存并映射到当前进程地址空间,然后向内存写入数据,直至遇到’#’为止;

2、读进程使用和写进程相同的KEY创建共享内存并映射到进程地址空间,然后从内存读数据并打印在终端上;

       3、注意通过一定的方式来实现读写进程之间的同步。

三、源程序

shm_write.c:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

#include"sem_com.h"



#define PATHNAME "."

#define PROJ_ID 0x66



int main() {

    // 生成KEY

    key_t key = ftok(PATHNAME, PROJ_ID);

    if (key < 0) {

        perror("生成KEY错误");

        exit(-1);

    }

    // 创建信号量

    int semId = semget(key, 1, IPC_CREAT);

    if (semId < 0) {

        perror("创建信号量失败");

        exit(-1);

    }

    // 初始化信号量

    init_sem(semId, 1);

    // 创建共享内存

    int shmId = shmget(key, 6666, IPC_CREAT);

    if (shmId < 0) {

        perror("创建共享内存失败");

        exit(-1);

    }

    // 映射共享内存

    char *addr = shmat(shmId, NULL, 0);

    sleep(1);

    int i = 0;

    while (1) {

        // P操作

        sem_p(semId);

        printf("write> ");

        char c = getchar();

        getchar();

        addr[i] = c;

        i++;

        addr[i] = 0;

        sleep(1);

        // V操作

        sem_v(semId);

        if (c == '#') {

            break;

        }

    }

    //解除共享内存映射

    shmdt(addr);

    sleep(2);

    return 0;

}

shm_read.c:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

#include"sem_com.h"



#define PATHNAME "."

#define PROJ_ID 0x66



// 原型声明

int indexOf(char *str1, char *str2);



int main() {

    // 生成KEY

    key_t key = ftok(PATHNAME, PROJ_ID);

    if (key < 0) {

        perror("生成KEY错误");

        exit(-1);

    }

    // 创建信号量

    int semId = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);

    if (semId < 0) {

        perror("创建信号量失败");

        exit(-1);

    }

    // 创建共享内存

    int shmId = shmget(key, 6666, 0666 | IPC_CREAT | IPC_EXCL);

    if (shmId < 0) {

        perror("创建共享内存失败");

        exit(-1);

    }

    // 映射共享内存

    char *addr = (char *) shmat(shmId, NULL, 0);

    sleep(5);

    int index = -1;

    while (1) {

        // P操作

        sem_p(semId);

        printf("read> %s\n", addr);

        sleep(1);

        // V操作

        sem_v(semId);

        if ((index = indexOf(addr, "#")) != -1) {

            break;

        }

    }

    // 解除共享内存映射

    shmdt(addr);

    sleep(2);

    // 删除信号量

    del_sem(semId);

    // 删除共享内存

    if (shmctl(shmId, IPC_RMID, NULL) < 0) {

        perror("删除共享内存失败");

        exit(-1);

    }

    return 0;

}



int indexOf(char *str1, char *str2) {

    char *p = str1;

    int i = 0;

    p = strstr(str1, str2);

    if (p == NULL)

        return -1;

    else {

        while (str1 != p) {

            str1++;

            i++;

        }

    }

    return i;

}

sem_com.h:

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

#include<unistd.h>



int init_sem(int sem_id, int init_value);

int del_sem(int sem_id);

int sem_p(int sem_id);

int sem_v(int sem_id);

sem_com.c:

#include"sem_com.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) < 0)

    {

        printf("init_sem");

        return -1;

    }

    return 0;

}



/*从系统中删除信号量*/

int del_sem(int sem_id)

{

    union semun sem_union;

    if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0)

    {

        printf("del_sem");

        return -1;

    }

    return 0;

}



/*P操作*/

int sem_p(int sem_id)

{

    struct sembuf sem_b;

    sem_b.sem_num = 0;

    sem_b.sem_op = -1;

    sem_b.sem_flg = SEM_UNDO;

    if (semop(sem_id, &sem_b, 1) < 0)

    {

        printf("sem_p");

        return -1;

    }

    return 0;

}



/*V操作*/

int sem_v(int sem_id)

{

    struct sembuf sem_b;

    sem_b.sem_num = 0;

    sem_b.sem_op = 1;

    sem_b.sem_flg = SEM_UNDO;

    if (semop(sem_id, &sem_b, 1) < 0)

    {

        printf("sem_v");

        return -1;

    }

    return 0;

}

makefile:

makelib: sem_com.o

    gcc sem_com.c -fPIC -shared -o libsem.so

shm: makelib

    cp libsem.so /lib

    gcc -o read shm_read.c -L. -lsem

    gcc -o write shm_write.c -L. -lsem

四、实验步骤、结果截图

(1)使用make工具编译源程序;

(2)测试运行,先运行read,再运行write。输入字符串,测试程序是否正确。

运行结果如下:

运行read的窗口:

运行write的窗口:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值