From 985ef22f64dd65da4dbeebccf23236fe59e380e2 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sat, 15 Oct 2022 15:33:47 +0800 Subject: [PATCH] add: [ipc] implementation of shm --- src/libipc/platform/posix/def.h | 17 +++ src/libipc/platform/posix/mmap.h | 27 ---- src/libipc/platform/posix/shm_impl.h | 125 ++++++++++++++++++ src/libipc/platform/win/get_sa.h | 4 + .../platform/win/{mmap.h => mmap_impl.h} | 29 +--- src/libipc/platform/win/shm_impl.h | 46 +++++++ src/libipc/platform/win/to_tchar.h | 4 + src/libipc/shm.cpp | 4 +- 8 files changed, 199 insertions(+), 57 deletions(-) create mode 100644 src/libipc/platform/posix/def.h delete mode 100644 src/libipc/platform/posix/mmap.h create mode 100644 src/libipc/platform/posix/shm_impl.h rename src/libipc/platform/win/{mmap.h => mmap_impl.h} (86%) create mode 100644 src/libipc/platform/win/shm_impl.h diff --git a/src/libipc/platform/posix/def.h b/src/libipc/platform/posix/def.h new file mode 100644 index 0000000..1032935 --- /dev/null +++ b/src/libipc/platform/posix/def.h @@ -0,0 +1,17 @@ +/** + * @file libipc/platform/posix/mmap.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include "libipc/def.h" + +LIBIPC_NAMESPACE_BEG_ +namespace posix { + +enum : int { + failed = -1, +}; + +} // namespace posix +LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/posix/mmap.h b/src/libipc/platform/posix/mmap.h deleted file mode 100644 index b2991fc..0000000 --- a/src/libipc/platform/posix/mmap.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file libipc/platform/posix/mmap.h - * @author mutouyun (orz@orzz.org) - */ -#pragma once - -#include -#include - -#include "libipc/shm.h" - -LIBIPC_NAMESPACE_BEG_ - -struct mmap_handle { - std::string file; - std::size_t f_sz; - std::size_t f_of; - void *memp; -}; - -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; - } -} - -LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/posix/shm_impl.h b/src/libipc/platform/posix/shm_impl.h new file mode 100644 index 0000000..d7bb2ea --- /dev/null +++ b/src/libipc/platform/posix/shm_impl.h @@ -0,0 +1,125 @@ +/** + * @file libipc/platform/posix/shm_impl.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +#include "libimp/log.h" +#include "libimp/system.h" + +#include "libipc/shm.h" + +#include "def.h" + +LIBIPC_NAMESPACE_BEG_ +using namespace ::LIBIMP_; + +struct shm_handle { + std::string file; + std::size_t f_sz; + void *memp; +}; + +/** + * @see https://man7.org/linux/man-pages/man3/shm_open.3.html + * https://man7.org/linux/man-pages/man3/fstat.3p.html + * https://man7.org/linux/man-pages/man3/ftruncate.3p.html + * https://man7.org/linux/man-pages/man2/mmap.2.html + */ +result shm_open(std::string name, std::size_t size, mode::type type) noexcept { + LIBIMP_LOG_(); + if (name.empty()) { + log.error("name is empty."); + return {}; + } + + /// @brief Open the object for read-write access. + int flag = O_RDWR; + switch (type) { + case mode::open: + size = 0; + break; + // The check for the existence of the object, + // and its creation if it does not exist, are performed atomically. + case mode::create: + flag |= O_CREAT | O_EXCL; + break; + // Create the shared memory object if it does not exist. + case mode::open | mode::create: + flag |= O_CREAT; + break; + default: + log.error("mode type is invalid. type = {}", type); + return {}; + } + + /// @brief Create/Open POSIX shared memory bject + int fd = ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH); + if (fd == posix::failed) { + log.error("shm_open fails. error = {}", sys::error_msg(sys::error_code())); + return {}; + } + + if (size == 0) { + /// @brief Try to get the size of this fd + struct stat st; + if (::fstat(fd, &st) == posix::failed) { + log.error("fstat fails. error = {}", sys::error_msg(sys::error_code())); + ::shm_unlink(name.c_str()); + return {}; + } + size = static_cast(st.st_size); + /// @brief Truncate this fd to a specified length + } else if (::ftruncate(fd, size) != 0) { + log.error("ftruncate fails. error = {}", sys::error_msg(sys::error_code())); + ::shm_unlink(name.c_str()); + return {}; + } + + /// @brief Creates a new mapping in the virtual address space of the calling process. + void *mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mem == MAP_FAILED) { + log.error("mmap fails. error = {}", sys::error_msg(sys::error_code())); + ::shm_unlink(name.c_str()); + return {}; + } + ::close(fd); + return new shm_handle{std::move(name), size, mem}; +} + +/** + * @see https://man7.org/linux/man-pages/man2/mmap.2.html + */ +result_code shm_close(shm_t h) noexcept { + LIBIMP_LOG_(); + if (h == nullptr) { + log.error("shm handle is null."); + return {}; + } + auto shm = static_cast(h); + if (shm->memp == nullptr) { + log.error("memory pointer is null."); + return {}; + } + if (::munmap(shm->memp, shm->f_sz) == posix::failed) { + auto ec = sys::error_code(); + log.error("munmap fails. error = {}", sys::error_msg(ec)); + return ec; + } + /// @brief no unlink the file. + delete shm; + return {true}; +} + +LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/win/get_sa.h b/src/libipc/platform/win/get_sa.h index 9965dd1..faea281 100644 --- a/src/libipc/platform/win/get_sa.h +++ b/src/libipc/platform/win/get_sa.h @@ -1,3 +1,7 @@ +/** + * @file libipc/platform/win/get_sa.h + * @author mutouyun (orz@orzz.org) + */ #pragma once #include diff --git a/src/libipc/platform/win/mmap.h b/src/libipc/platform/win/mmap_impl.h similarity index 86% rename from src/libipc/platform/win/mmap.h rename to src/libipc/platform/win/mmap_impl.h index b0cf7f5..494532c 100644 --- a/src/libipc/platform/win/mmap.h +++ b/src/libipc/platform/win/mmap_impl.h @@ -1,5 +1,5 @@ /** - * @file libipc/platform/win/mmap.h + * @file libipc/platform/win/mmap_impl.h * @author mutouyun (orz@orzz.org) */ #pragma once @@ -150,31 +150,4 @@ void mmap_release(HANDLE h, LPCVOID mem) { } } // namespace - -::LIBIMP_::result shm_open(std::string name, std::size_t size, mode::type type) noexcept { - LIBIMP_LOG_(); - auto h = mmap_open(name, size, type); - if (h == NULL) { - log.error("mmap_open failed."); - return {nullptr, *sys::error_code()}; - } - auto mem = mmap_memof(h); - if (mem == NULL) { - log.warning("mmap_memof failed."); - } - return new shm_handle{std::move(name), mmap_sizeof(mem), mem, h}; -} - -::LIBIMP_::result_code shm_close(shm_t h) noexcept { - LIBIMP_LOG_(); - if (h == nullptr) { - log.error("shm handle is null."); - return {}; - } - auto shm = static_cast(h); - mmap_release(shm->h_fmap, shm->memp); - delete shm; - return {true}; -} - LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/win/shm_impl.h b/src/libipc/platform/win/shm_impl.h new file mode 100644 index 0000000..0df9a8f --- /dev/null +++ b/src/libipc/platform/win/shm_impl.h @@ -0,0 +1,46 @@ +/** + * @file libipc/platform/win/shm_impl.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include + +#include "libimp/log.h" +#include "libimp/system.h" + +#include "libipc/shm.h" + +#include "mmap_impl.h" + +LIBIPC_NAMESPACE_BEG_ +using namespace ::LIBIMP_; + +result shm_open(std::string name, std::size_t size, mode::type type) noexcept { + LIBIMP_LOG_(); + auto h = mmap_open(name, size, type); + if (h == NULL) { + log.error("mmap_open failed."); + return {nullptr, *sys::error_code()}; + } + auto mem = mmap_memof(h); + if (mem == NULL) { + log.warning("mmap_memof failed."); + } + return new shm_handle{std::move(name), mmap_sizeof(mem), mem, h}; +} + +result_code shm_close(shm_t h) noexcept { + LIBIMP_LOG_(); + if (h == nullptr) { + log.error("shm handle is null."); + return {}; + } + auto shm = static_cast(h); + mmap_release(shm->h_fmap, shm->memp); + delete shm; + return {true}; +} + +LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/win/to_tchar.h b/src/libipc/platform/win/to_tchar.h index a571c9b..4f1d942 100644 --- a/src/libipc/platform/win/to_tchar.h +++ b/src/libipc/platform/win/to_tchar.h @@ -1,3 +1,7 @@ +/** + * @file libipc/platform/win/to_tchar.h + * @author mutouyun (orz@orzz.org) + */ #pragma once #include diff --git a/src/libipc/shm.cpp b/src/libipc/shm.cpp index 9522e7c..da15fb5 100644 --- a/src/libipc/shm.cpp +++ b/src/libipc/shm.cpp @@ -3,9 +3,9 @@ #include "libimp/detect_plat.h" #if defined(LIBIMP_OS_WIN) -#include "libipc/platform/win/mmap.h" +#include "libipc/platform/win/shm_impl.h" #else -#include "libipc/platform/posix/mmap.h" +#include "libipc/platform/posix/shm_impl.h" #endif LIBIPC_NAMESPACE_BEG_