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);
        }
        munmap(pMem, sizeof(proto_data_t)); // 解除内存映射
        shm_unlink(shm_obj); // 父进程删除内核的共享内存实例
        exit(EXIT_SUCCESS);
    }
    
    return 0;
}
test




















