mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
add: [ipc] implementation of memory mapping (TBD)
This commit is contained in:
parent
e4add79508
commit
9e625b603b
@ -10,8 +10,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#define LIBIPC_ ipc
|
#define LIBIPC_ ipc
|
||||||
#define LIBIPC_NAMESPACE_ LIBIPC_
|
#define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_ {
|
||||||
#define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_NAMESPACE_ {
|
|
||||||
#define LIBIPC_NAMESPACE_END_ }
|
#define LIBIPC_NAMESPACE_END_ }
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
@ -27,4 +26,13 @@ struct prot {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mode {
|
||||||
|
using type = std::uint32_t;
|
||||||
|
enum : type {
|
||||||
|
none = 0x00,
|
||||||
|
create = 0x01,
|
||||||
|
open = 0x02,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_END_
|
LIBIPC_NAMESPACE_END_
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file libipc/mmap.h
|
|
||||||
* @author mutouyun (orz@orzz.org)
|
|
||||||
* @brief Define the methods of memory-mapped file I/O
|
|
||||||
* @date 2022-04-17
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
#include "libimp/export.h"
|
|
||||||
#include "libimp/result.h"
|
|
||||||
|
|
||||||
#include "libipc/def.h"
|
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
|
||||||
|
|
||||||
struct mmap_handle;
|
|
||||||
using mmap_t = mmap_handle *;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Creates a new mapping in the virtual address space of the calling process.
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT ::LIBIMP_::result<mmap_t> mmap_open(std::string const &file,
|
|
||||||
std::size_t size = 0,
|
|
||||||
prot::type = prot::read | prot::write) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Close the memory mapping handle.
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT ::LIBIMP_::result_code mmap_close(mmap_t) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Synchronize a file with a memory map.
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT ::LIBIMP_::result_code mmap_sync(mmap_t) noexcept;
|
|
||||||
|
|
||||||
LIBIMP_EXPORT void * mmap_get (mmap_t) noexcept;
|
|
||||||
LIBIMP_EXPORT std::size_t mmap_size(mmap_t) noexcept;
|
|
||||||
LIBIMP_EXPORT std::string mmap_file(mmap_t) noexcept;
|
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_END_
|
|
||||||
@ -6,10 +6,37 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "libimp/export.h"
|
||||||
|
#include "libimp/result.h"
|
||||||
|
|
||||||
#include "libipc/def.h"
|
#include "libipc/def.h"
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
struct shm_handle;
|
||||||
|
using shm_t = shm_handle *;
|
||||||
|
|
||||||
|
/// @brief Create a new shared memory handle with a name of the shared memory file.
|
||||||
|
LIBIMP_EXPORT ::LIBIMP_::result<shm_t> shm_open(std::string name,
|
||||||
|
std::size_t size = 0,
|
||||||
|
mode::type = mode::create | mode::open) noexcept;
|
||||||
|
|
||||||
|
/// @brief Close the shared memory handle.
|
||||||
|
LIBIMP_EXPORT ::LIBIMP_::result_code shm_close(shm_t) noexcept;
|
||||||
|
|
||||||
|
/// @brief Gets a memory pointer based on the shared memory handle.
|
||||||
|
/// @return nullptr on failure.
|
||||||
|
LIBIMP_EXPORT void *shm_get(shm_t) noexcept;
|
||||||
|
|
||||||
|
/// @brief Gets the memory size based on the shared memory handle.
|
||||||
|
/// @return 0 on failure.
|
||||||
|
LIBIMP_EXPORT std::size_t shm_size(shm_t) noexcept;
|
||||||
|
|
||||||
|
/// @brief Gets the name of the shared memory file based on the shared memory handle.
|
||||||
|
/// @return empty string on failure.
|
||||||
|
LIBIMP_EXPORT std::string shm_file(shm_t) noexcept;
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_END_
|
LIBIPC_NAMESPACE_END_
|
||||||
|
|||||||
@ -42,7 +42,7 @@ std::string error_str(result_code code) noexcept {
|
|||||||
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
|
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
if (::strerror_r((int)code.value(), msg_buf, sizeof(msg_buf)) != 0) {
|
if (::strerror_r((int)code.value(), msg_buf, sizeof(msg_buf)) != 0) {
|
||||||
log.error("strerror_r fails. return = {}", error_code());
|
log.error("strerror_r fails. error = {}", error_code());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return msg_buf;
|
return msg_buf;
|
||||||
|
|||||||
@ -56,7 +56,7 @@ std::string error_str(result_code code) noexcept {
|
|||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(LPTSTR)&lpErrText,
|
(LPTSTR)&lpErrText,
|
||||||
0, NULL) == 0) {
|
0, NULL) == 0) {
|
||||||
log.error("FormatMessage fails. return = {}", error_code());
|
log.error("FormatMessage fails. error = {}", error_code());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
LIBIMP_UNUSED auto buf_guard = std::unique_ptr<std::remove_pointer_t<LPVOID>,
|
LIBIMP_UNUSED auto buf_guard = std::unique_ptr<std::remove_pointer_t<LPVOID>,
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
#include "libipc/mmap.h"
|
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_END_
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/posix/mmap.h
|
* @file libipc/platform/posix/mmap.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* @author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -7,7 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include "libipc/mmap.h"
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ struct mmap_handle {
|
|||||||
void *memp;
|
void *memp;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int mmap_open_(mmap_t *h_out, std::string const &file, int fd, int flags, std::size_t f_sz, std::size_t f_of) noexcept {
|
inline int mmap_open_(mmap_handle *h_out, std::string const &file, int fd, int flags, std::size_t f_sz, std::size_t f_of) noexcept {
|
||||||
if (h_out == nullptr) {
|
if (h_out == nullptr) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/libipc/platform/win/get_sa.h
Normal file
46
src/libipc/platform/win/get_sa.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <securitybaseapi.h>
|
||||||
|
|
||||||
|
#include "libimp/system.h"
|
||||||
|
#include "libimp/log.h"
|
||||||
|
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a SECURITY_ATTRIBUTES structure singleton
|
||||||
|
* @see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85)
|
||||||
|
*/
|
||||||
|
inline LPSECURITY_ATTRIBUTES get_sa() {
|
||||||
|
static struct initiator {
|
||||||
|
|
||||||
|
SECURITY_DESCRIPTOR sd_;
|
||||||
|
SECURITY_ATTRIBUTES sa_;
|
||||||
|
|
||||||
|
bool succ_ = false;
|
||||||
|
|
||||||
|
initiator() {
|
||||||
|
using namespace ::LIBIMP_;
|
||||||
|
log::gripper log {"get_sa"};
|
||||||
|
if (!::InitializeSecurityDescriptor(&sd_, SECURITY_DESCRIPTOR_REVISION)) {
|
||||||
|
log.error("InitializeSecurityDescriptor fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!::SetSecurityDescriptorDacl(&sd_, TRUE, NULL, FALSE)) {
|
||||||
|
log.error("SetSecurityDescriptorDacl fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sa_.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
sa_.bInheritHandle = FALSE;
|
||||||
|
sa_.lpSecurityDescriptor = &sd_;
|
||||||
|
succ_ = true;
|
||||||
|
}
|
||||||
|
} handle;
|
||||||
|
return handle.succ_ ? &handle.sa_ : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
138
src/libipc/platform/win/mmap.h
Normal file
138
src/libipc/platform/win/mmap.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* @file libipc/platform/win/mmap.h
|
||||||
|
* @author mutouyun (orz@orzz.org)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "libimp/log.h"
|
||||||
|
#include "libimp/system.h"
|
||||||
|
|
||||||
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
|
#include "get_sa.h"
|
||||||
|
#include "to_tchar.h"
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
using namespace ::LIBIMP_;
|
||||||
|
|
||||||
|
struct shm_handle {
|
||||||
|
std::string file;
|
||||||
|
std::size_t f_sz;
|
||||||
|
void *memp;
|
||||||
|
HANDLE h_fmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void mmap_close(HANDLE h) {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// @brief Closes an open object handle.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
|
||||||
|
if (!::CloseHandle(h)) {
|
||||||
|
log.error("CloseHandle fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE mmap_open(std::string file, std::size_t size, mode::type type) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (file.empty()) {
|
||||||
|
log.error("file name is empty.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
auto t_name = detail::to_tstring(file);
|
||||||
|
if (t_name.empty()) {
|
||||||
|
log.error("file name is empty. (TCHAR conversion failed)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/// @brief Opens a named file mapping object.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilemappinga
|
||||||
|
if (type == mode::open) {
|
||||||
|
HANDLE h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, t_name.c_str());
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("OpenFileMapping fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
/// @brief Creates or opens a named or unnamed file mapping object for a specified file.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
||||||
|
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT,
|
||||||
|
0, static_cast<DWORD>(size), t_name.c_str());
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("CreateFileMapping fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// If the object exists before the function call, the function returns a handle to the existing object
|
||||||
|
// (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS.
|
||||||
|
if ((type == mode::create) && (::GetLastError() == ERROR_ALREADY_EXISTS)) {
|
||||||
|
mmap_close(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID mmap_memof(HANDLE h) {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/// @brief Maps a view of a file mapping into the address space of a calling process.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile
|
||||||
|
LPVOID mem = ::MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("MapViewOfFile fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T mmap_sizeof(LPCVOID mem) {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (mem == NULL) {
|
||||||
|
log.error("memory pointer is null.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/// @brief Retrieves information about a range of pages in the virtual address space of the calling process.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery
|
||||||
|
MEMORY_BASIC_INFORMATION mem_info {};
|
||||||
|
if (::VirtualQuery(mem, &mem_info, sizeof(mem_info)) == 0) {
|
||||||
|
log.error("VirtualQuery fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return mem_info.RegionSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_release(HANDLE h, LPCVOID mem) {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (h == NULL) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mem == NULL) {
|
||||||
|
log.error("memory pointer is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// @brief Unmaps a mapped view of a file from the calling process's address space.
|
||||||
|
/// @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile
|
||||||
|
if (!::UnmapViewOfFile(mem)) {
|
||||||
|
log.warning("UnmapViewOfFile fails. error = {}", sys::error_msg(sys::error_code()));
|
||||||
|
}
|
||||||
|
mmap_close(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
::LIBIMP_::result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
23
src/libipc/platform/win/to_tchar.h
Normal file
23
src/libipc/platform/win/to_tchar.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "libimp/codecvt.h"
|
||||||
|
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
using tstring = std::basic_string<TCHAR>;
|
||||||
|
|
||||||
|
inline tstring to_tstring(std::string const &str) {
|
||||||
|
tstring des;
|
||||||
|
::LIBIMP_::cvt_sstr(str, des);
|
||||||
|
return des;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
12
src/libipc/shm.cpp
Normal file
12
src/libipc/shm.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "libimp/detect_plat.h"
|
||||||
|
#if defined(LIBIMP_OS_WIN)
|
||||||
|
#include "libipc/platform/win/mmap.h"
|
||||||
|
#else
|
||||||
|
#include "libipc/platform/posix/mmap.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
#include "libipc/mmap.h"
|
|
||||||
|
|
||||||
TEST(mmap, create_close) {
|
|
||||||
}
|
|
||||||
7
test/test_ipc_shm.cpp
Normal file
7
test/test_ipc_shm.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
|
TEST(shm, create_close) {
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user