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
#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
const char* klocal_basename = "Local\\shared_memory_ccj_";
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;
}
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;
}
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);
}