posix ipc之共享内存

该代码示例展示了在Linux中如何使用shm_open创建内核共享内存,通过ftruncate设置大小,然后利用mmap进行映射,实现父子进程间的通信。父进程初始化共享内存并写入数据,子进程读取并修改数据,实现了数据的交换。
摘要由CSDN通过智能技术生成

note

1.shm_open的pathname不能带路径名,shm_open的创建目录为/dev/shm

2.使用ftruncate设置内核共享内存实例的大小

3.使用mmap进行有名映射(实例反应在文件系统的一个文件)

code

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/types.h>

#define PARENT_WRITABLE 111
#define CHILD_READABLE 222
typedef  struct proto_data {
    int flag;
    char text[1020];
}proto_data_t;

int main(int argc, char** argv) {
    int shm_id = -1;
    const char* shm_obj = "shm_obj";    /* shm_open的pathname不能带路径名,shm_open的创建目录为/dev/shm */
    pid_t pid = 0;
    void* pMem = NULL;
    int ret = -1;

    // 父进程创建共享内存实例(位于内核)
    shm_id = shm_open(shm_obj, O_CREAT|O_RDWR, S_IRWXU|S_IRGRP|S_IROTH);
    if (shm_id == -1) {
        fprintf(stderr, "shm_open error,%s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "shm_open success,shm_id:%d\n", shm_id);

    // 设置共享内存的大小
    ret = ftruncate(shm_id, sizeof(proto_data_t));
    if (ret == -1) {
        fprintf(stderr, "ftruncate error,%s\n", strerror(errno));
        shm_unlink(shm_obj); // 删除内核的共享内存实例
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fork error,%s\n", strerror(errno));
        shm_unlink(shm_obj); // 删除内核的共享内存实例
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "fork success\n");

    if (pid == 0) { // child
        int i = 0;
        proto_data_t* data = NULL;
        pMem = mmap(NULL, sizeof(proto_data_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0);  // 内存映射
        if (pMem == MAP_FAILED) {
            fprintf(stderr, "child process mmap error,%s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
        fprintf(stdout, "child mmap success\n");
        data = pMem;
        for (int i = 0; i < 10; ++i) {
            fprintf(stdout, "child process in loop\n");
            if (data->flag == CHILD_READABLE) {
                fprintf(stdout, "child read:%s\n", data->text);
                data->flag = PARENT_WRITABLE;
            }
            sleep(1);
        }
        munmap(pMem, sizeof(proto_data_t)); // 解除内存映射
        exit(EXIT_SUCCESS);
    }
    else if (pid > 0) { // parent
        int i = 0;
        proto_data_t* data = NULL;
        time_t t = 0;
        pMem = mmap(NULL, sizeof(proto_data_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0);  // 内存映射
        if (pMem == MAP_FAILED) {
            fprintf(stderr, "parent process mmap error,%s\n", strerror(errno));
            shm_unlink(shm_obj); // 父进程删除内核的共享内存实例
            exit(EXIT_FAILURE);
        }
        fprintf(stdout, "parent mmap success\n");
        data = pMem;
        data->flag = PARENT_WRITABLE;
        fprintf(stdout, "parent data->flag set success\n");
        for (int i = 0; i < 10; ++i) {
            fprintf(stdout, "parent process in loop\n");
            if (data->flag == PARENT_WRITABLE) {
                memset(data->text, 0, sizeof(data->text));
                time(&t);
                sprintf(data->text, "writen by parent,%s", ctime(&t));
                data->flag = CHILD_READABLE;
            }
            sleep(1);
        }
        wait(NULL); // 回收子进程资源
        munmap(pMem, sizeof(proto_data_t)); // 解除内存映射
        shm_unlink(shm_obj); // 父进程删除内核的共享内存实例
        exit(EXIT_SUCCESS);
    }
    
    return 0;
}

test

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值