WINDOWS 共享内存

WINDOWS 共享内存

简单理解

多个进程可以访问的内存。

实现

shared_memory_win.h

#pragma once

#include <stdint.h>

int create_shared_memory(const uint64_t size, const char* name, void** p_handle, char** p_buffer);
int open_shared_memory(const uint64_t size, const char* name, void** p_handle, char** p_buffer);

void close_shared_memory(void** p_handle, char** p_buffer);

shared_memory_win.cc

// 文件: shared_memory_win.cc
// 时间: 2024-08-27
// 来自: ccj
// 描述: 共享内存的封装
//          创建
//          打开
//          注销

#include "shared_memory_win.h"


#include <stdio.h>
#include <assert.h>

#include <Windows.h>

#ifndef _WIN32
    #error This source file require winapi functions
#endif


#ifdef _DEBUG
    #define debug(m, ...) fprintf(stderr, "[%s:%d] " m "\n", __FILE__, __LINE__, __VA_ARGS__)
#else
    #define debug(m, ...)
#endif


// 以Local开头是用户级共享内存
// 以Global开头是系统级共享内存,运行时要管理员权限
const char* klocal_basename = "Local\\shared_memory_ccj_";


/// @brief 创建共享内存
/// @param size 共享内存大小
/// @param name 共享内存唯一标识
/// @param p_handle 指向共享内存句柄
/// @param p_buffer 指向共享内存地址
/// @return 成功返回0
int create_shared_memory(const uint64_t size, const char* name, void** p_handle, char** p_buffer) {
    assert(p_handle != nullptr);
    assert(p_buffer != nullptr);
    if (p_handle == nullptr) return -1;
    if (p_buffer == nullptr) return -1;


    void* handle = nullptr;
    char* buffer = nullptr;

    // 权限
    PSECURITY_DESCRIPTOR pSec = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (!pSec) {
        debug("LocalAlloc failed");
        return -1;
    }

    bool ret = InitializeSecurityDescriptor(pSec, SECURITY_DESCRIPTOR_REVISION);
    if (!ret) {
        debug("InitializeSecurityDescriptor failed");
        return -1;
    }

    ret = SetSecurityDescriptorDacl(pSec, TRUE, NULL, TRUE);
    if (!ret) {
        debug("SetSecurityDescriptorDacl failed");
        return -1;
    }


    // 创建
    SECURITY_ATTRIBUTES attr;
    attr.bInheritHandle = FALSE;
    attr.lpSecurityDescriptor = pSec;
    attr.nLength = sizeof(SECURITY_ATTRIBUTES);

    uint32_t size_higt = (uint32_t)(size >> 32);
    uint32_t size_low = (uint32_t)size;
    char map_name[64] = {0};
    sprintf_s(map_name, 64, "%s%s", klocal_basename, name);

    handle = CreateFileMapping(INVALID_HANDLE_VALUE, &attr, PAGE_READWRITE, size_higt, size_low, map_name);
    if (handle == NULL) {
        LocalFree(pSec);
        int err_no = GetLastError();
        debug("CreateFileMapping failed. Error number: %d, Error: %s", err_no, strerror(err_no));
        return err_no;
    }


    // 地址
    buffer = (char*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, size);
    if (buffer == NULL) {
        LocalFree(pSec);
        CloseHandle(handle);

        int err_no = GetLastError();
        debug("MapViewOfFile failed. Error number: %d, Error: %s", err_no, strerror(err_no));
        return err_no;
    }

    // 返回
    *p_handle = handle;
    *p_buffer = buffer;
    LocalFree(pSec);

    return 0;
}


/// @brief 打开已创建的共享内存
/// @param size 共享内存大小
/// @param name 共享内存唯一标识
/// @param p_handle 指向共享内存句柄
/// @param p_buffer 指向共享内存地址
/// @return 成功返回0
int open_shared_memory(const uint64_t size, const char* name, void** p_handle, char** p_buffer) {
    assert(p_handle != nullptr);
    assert(p_buffer != nullptr);
    if (p_handle == nullptr) return -1;
    if (p_buffer == nullptr) return -1;


    void* handle = nullptr;
    char* buffer = nullptr;

    // 打开
    char map_name[64] = {0};
    sprintf_s(map_name, 64, "%s%s", klocal_basename, name);

    handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, map_name);
    if (handle == NULL) {
        int err_no = GetLastError();
        debug("OpenFileMapping failed. Error number: %d, Error: %s", err_no, strerror(err_no));
        return err_no;
    }


    // 地址
    buffer = (char*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, size);
    if (buffer == NULL) {
        CloseHandle(handle);

        int err_no = GetLastError();
        debug("OpenFileMapping failed. Error number: %d, Error: %s", err_no, strerror(err_no));
        return err_no;
    }

    // 返回
    *p_handle = handle;
    *p_buffer = buffer;
    return 0;
}


/// @brief 关闭句柄和内存
/// 只有所有连接到共享内存的句柄关闭才能真正释放共享内存
/// @param p_handle 指向共享内存句柄
/// @param p_buffer 指向共享内存地址
/// @return
void close_shared_memory(void** p_handle, char** p_buffer) {
    if (*p_buffer) {
        UnmapViewOfFile(*p_buffer);
        *p_buffer = nullptr;
    }
    if (*p_handle) {
        CloseHandle(*p_handle);
        *p_handle = nullptr;
    }
}

测试用例

创建用例

#include <thread>

#include "shared_memory_win.h"
#include "base/debug.h"


int main() {
    const uint64_t shared_memory_size = (uint64_t)1024 * 1024 * 1024 * 10;
    debug("map size %lluG", shared_memory_size / 1024 / 1024 / 1024);

    int err_no = 0;
    void* handle = nullptr;
    char* buffer = nullptr;


    // 创建
    err_no = create_shared_memory(shared_memory_size, "1", &handle, &buffer);
    if (err_no) {
        debug("create_shared_memory failed, err: %s", strerror(err_no));
        return -1;
    }
    debug("create_shared_memory done, handle: %llu, buffer: %llu", (uint64_t)handle, (uint64_t)buffer);
    std::memset(buffer, 0, shared_memory_size);


    // 写
    int* start_buffer = (int*)buffer;
    int* end_buffer = (int*)(buffer + shared_memory_size - 4);
    *(start_buffer) = 0x12345678;
    *(end_buffer) = 0xAA5555AA;
    debug("wirte, start: 0x%X, end: 0x%X", *start_buffer, *end_buffer);


    // 释放
    std::this_thread::sleep_for(std::chrono::seconds(10));
    close_shared_memory(&handle, &buffer);
}

打开用例

注意: 打开用例要等一下创建用例的创建和memset,不然读不到0x12345678
#include <thread>

#include "shared_memory_win.h"
#include "base/debug.h"

int main() {
    const uint64_t shared_memory_size = (uint64_t)1024 * 1024 * 1024 * 10;
    debug("map size %lluG", shared_memory_size / 1024 / 1024 / 1024);

    int err_no = 0;
    void* handle = nullptr;
    char* buffer = nullptr;

    // 打开
    err_no = open_shared_memory(shared_memory_size, "1", &handle, &buffer);
    if (err_no) {
        debug("open_shared_memory failed, err: %s", strerror(err_no));
        return -1;
    }
    debug("open_shared_memory done, handle: %llu, buffer: %llu", (uint64_t)handle, (uint64_t)buffer);

    // 读
    int* start_buffer = (int*)buffer;
    int* end_buffer = (int*)(buffer + shared_memory_size - 4);
    debug("read, start: 0x%X, end: 0x%X", *start_buffer, *end_buffer);

    // 释放
    std::this_thread::sleep_for(std::chrono::seconds(5));
    close_shared_memory(&handle, &buffer);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值