diff --git a/include/libipc/def.h b/include/libipc/def.h index dd04e07..0561ffe 100755 --- a/include/libipc/def.h +++ b/include/libipc/def.h @@ -10,8 +10,7 @@ #include #define LIBIPC_ ipc -#define LIBIPC_NAMESPACE_ LIBIPC_ -#define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_NAMESPACE_ { +#define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_ { #define LIBIPC_NAMESPACE_END_ } 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_ diff --git a/include/libipc/mmap.h b/include/libipc/mmap.h deleted file mode 100644 index 2f9e921..0000000 --- a/include/libipc/mmap.h +++ /dev/null @@ -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 -#include - -#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_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_ diff --git a/include/libipc/shm.h b/include/libipc/shm.h index b2ed519..c7e697d 100644 --- a/include/libipc/shm.h +++ b/include/libipc/shm.h @@ -6,10 +6,37 @@ */ #pragma once +#include +#include + +#include "libimp/export.h" +#include "libimp/result.h" + #include "libipc/def.h" 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_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_ diff --git a/src/libimp/platform/posix/system.h b/src/libimp/platform/posix/system.h index a786ab4..3f5f33d 100644 --- a/src/libimp/platform/posix/system.h +++ b/src/libimp/platform/posix/system.h @@ -42,7 +42,7 @@ std::string error_str(result_code code) noexcept { #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) LIBIMP_LOG_(); 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 msg_buf; diff --git a/src/libimp/platform/win/system.h b/src/libimp/platform/win/system.h index d412a65..9fac939 100644 --- a/src/libimp/platform/win/system.h +++ b/src/libimp/platform/win/system.h @@ -56,7 +56,7 @@ std::string error_str(result_code code) noexcept { MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpErrText, 0, NULL) == 0) { - log.error("FormatMessage fails. return = {}", error_code()); + log.error("FormatMessage fails. error = {}", error_code()); return {}; } LIBIMP_UNUSED auto buf_guard = std::unique_ptr, diff --git a/src/libipc/mmap.cpp b/src/libipc/mmap.cpp deleted file mode 100644 index 06fb539..0000000 --- a/src/libipc/mmap.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "libipc/mmap.h" - -LIBIPC_NAMESPACE_BEG_ - - - -LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/posix/mmap.h b/src/libipc/platform/posix/mmap.h index 8aef07b..b2991fc 100644 --- a/src/libipc/platform/posix/mmap.h +++ b/src/libipc/platform/posix/mmap.h @@ -1,5 +1,5 @@ /** - * @file libimp/platform/posix/mmap.h + * @file libipc/platform/posix/mmap.h * @author mutouyun (orz@orzz.org) */ #pragma once @@ -7,7 +7,7 @@ #include #include -#include "libipc/mmap.h" +#include "libipc/shm.h" LIBIPC_NAMESPACE_BEG_ @@ -18,7 +18,7 @@ struct mmap_handle { 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) { return -1; } diff --git a/src/libipc/platform/win/get_sa.h b/src/libipc/platform/win/get_sa.h new file mode 100644 index 0000000..9965dd1 --- /dev/null +++ b/src/libipc/platform/win/get_sa.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#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_ \ No newline at end of file diff --git a/src/libipc/platform/win/mmap.h b/src/libipc/platform/win/mmap.h new file mode 100644 index 0000000..92b4d9b --- /dev/null +++ b/src/libipc/platform/win/mmap.h @@ -0,0 +1,138 @@ +/** + * @file libipc/platform/win/mmap.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include + +#include + +#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(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_open(std::string name, std::size_t size, mode::type type) noexcept { + return {}; +} + +LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/win/to_tchar.h b/src/libipc/platform/win/to_tchar.h new file mode 100644 index 0000000..a571c9b --- /dev/null +++ b/src/libipc/platform/win/to_tchar.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include + +#include "libimp/codecvt.h" + +#include "libipc/def.h" + +LIBIPC_NAMESPACE_BEG_ +namespace detail { + +using tstring = std::basic_string; + +inline tstring to_tstring(std::string const &str) { + tstring des; + ::LIBIMP_::cvt_sstr(str, des); + return des; +} + +} // namespace detail +LIBIPC_NAMESPACE_END_ \ No newline at end of file diff --git a/src/libipc/shm.cpp b/src/libipc/shm.cpp new file mode 100644 index 0000000..dad96d9 --- /dev/null +++ b/src/libipc/shm.cpp @@ -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_ diff --git a/test/test_ipc_mmap.cpp b/test/test_ipc_mmap.cpp deleted file mode 100644 index 40ed6bb..0000000 --- a/test/test_ipc_mmap.cpp +++ /dev/null @@ -1,7 +0,0 @@ - -#include "gtest/gtest.h" - -#include "libipc/mmap.h" - -TEST(mmap, create_close) { -} \ No newline at end of file diff --git a/test/test_ipc_shm.cpp b/test/test_ipc_shm.cpp new file mode 100644 index 0000000..1e5c95f --- /dev/null +++ b/test/test_ipc_shm.cpp @@ -0,0 +1,7 @@ + +#include "gtest/gtest.h" + +#include "libipc/shm.h" + +TEST(shm, create_close) { +} \ No newline at end of file