#ifndef VRSHAREMEM_LIBRARY #define VRSHAREMEM_LIBRARY #endif #include "VrShareMem.h" #include "VrError.h" #include #include #ifdef _WIN32 #include #else #include #include #endif VrShareMem::VrShareMem() : m_size(0) , m_mappedAddress(nullptr) , m_created(false) { #ifdef _WIN32 m_hMapFile = nullptr; #else m_fd = -1; #endif } VrShareMem::~VrShareMem() { Close(); } int VrShareMem::CreateOrOpen(const std::string& name, size_t size, bool create) { if (name.empty() || size == 0) { return ERR_CODE(SHAREMEM_ERR_PARAM); // 参数错误 } // 先关闭已有的 Close(); m_name = name; m_size = size; m_created = create; std::string platformName = GetPlatformName(name); #ifdef _WIN32 if (create) { // 创建新的共享内存 m_hMapFile = CreateFileMappingA( INVALID_HANDLE_VALUE, // 使用页面文件 nullptr, // 默认安全性 PAGE_READWRITE, // 读写访问 0, // 高32位大小 static_cast(size), // 低32位大小 platformName.c_str() // 对象名称 ); if (m_hMapFile == nullptr) { return ERR_CODE(SHAREMEM_ERR_CREATE); // 创建失败 } // 检查是否已存在 if (GetLastError() == ERROR_ALREADY_EXISTS && create) { CloseHandle(m_hMapFile); m_hMapFile = nullptr; return ERR_CODE(SHAREMEM_ERR_ALREADY_EXIST); // 已存在 } } else { // 打开已存在的共享内存 m_hMapFile = OpenFileMappingA( FILE_MAP_ALL_ACCESS, // 读写访问 FALSE, // 不继承句柄 platformName.c_str() // 对象名称 ); if (m_hMapFile == nullptr) { return ERR_CODE(SHAREMEM_ERR_NOT_EXIST); // 打开失败 } } #else // Linux 实现 if (create) { // 创建新的共享内存 m_fd = shm_open(platformName.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666); if (m_fd == -1) { if (errno == EEXIST) { return ERR_CODE(SHAREMEM_ERR_ALREADY_EXIST); // 已存在 } return ERR_CODE(SHAREMEM_ERR_CREATE); // 创建失败 } // 设置大小 if (ftruncate(m_fd, size) == -1) { close(m_fd); shm_unlink(platformName.c_str()); m_fd = -1; return ERR_CODE(SHAREMEM_ERR_SIZE); // 设置大小失败 } } else { // 打开已存在的共享内存 m_fd = shm_open(platformName.c_str(), O_RDWR, 0666); if (m_fd == -1) { return ERR_CODE(SHAREMEM_ERR_NOT_EXIST); // 打开失败 } // 获取实际大小 struct stat st; if (fstat(m_fd, &st) == -1) { close(m_fd); m_fd = -1; return ERR_CODE(SHAREMEM_ERR_INFO); // 获取信息失败 } m_size = st.st_size; } #endif return SUCCESS; // 成功 } void* VrShareMem::MapView() { if (!IsValid()) { return nullptr; } if (m_mappedAddress != nullptr) { return m_mappedAddress; // 已经映射 } #ifdef _WIN32 m_mappedAddress = MapViewOfFile( m_hMapFile, // 文件映射对象句柄 FILE_MAP_ALL_ACCESS, // 读写访问 0, // 高32位偏移 0, // 低32位偏移 m_size // 映射大小 ); #else m_mappedAddress = mmap( nullptr, // 系统选择地址 m_size, // 映射大小 PROT_READ | PROT_WRITE, // 读写权限 MAP_SHARED, // 共享映射 m_fd, // 文件描述符 0 // 偏移量 ); if (m_mappedAddress == MAP_FAILED) { m_mappedAddress = nullptr; } #endif return m_mappedAddress; } int VrShareMem::UnmapView() { if (m_mappedAddress == nullptr) { return SUCCESS; // 已经取消映射 } #ifdef _WIN32 if (!UnmapViewOfFile(m_mappedAddress)) { return ERR_CODE(APP_ERR_EXEC); // 取消映射失败 } #else if (munmap(m_mappedAddress, m_size) == -1) { return ERR_CODE(APP_ERR_EXEC); // 取消映射失败 } #endif m_mappedAddress = nullptr; return SUCCESS; } int VrShareMem::Close() { // 取消映射 UnmapView(); #ifdef _WIN32 if (m_hMapFile != nullptr) { CloseHandle(m_hMapFile); m_hMapFile = nullptr; } #else if (m_fd != -1) { close(m_fd); // 如果是创建者,删除共享内存 if (m_created) { std::string platformName = GetPlatformName(m_name); shm_unlink(platformName.c_str()); } m_fd = -1; } #endif m_size = 0; m_name.clear(); m_created = false; return SUCCESS; } size_t VrShareMem::GetSize() const { return m_size; } void* VrShareMem::GetMappedAddress() const { return m_mappedAddress; } bool VrShareMem::IsValid() const { #ifdef _WIN32 return m_hMapFile != nullptr; #else return m_fd != -1; #endif } int VrShareMem::WriteData(size_t offset, const void* data, size_t size) { if (!CheckBounds(offset, size) || data == nullptr) { return ERR_CODE(SHAREMEM_ERR_PARAM); } if (m_mappedAddress == nullptr) { return ERR_CODE(SHAREMEM_ERR_NOT_MAPPED); // 未映射 } std::lock_guard lock(m_mutex); char* dest = static_cast(m_mappedAddress) + offset; std::memcpy(dest, data, size); return static_cast(size); } int VrShareMem::ReadData(size_t offset, void* buffer, size_t size) { if (!CheckBounds(offset, size) || buffer == nullptr) { return ERR_CODE(SHAREMEM_ERR_PARAM); } if (m_mappedAddress == nullptr) { return ERR_CODE(SHAREMEM_ERR_NOT_MAPPED); // 未映射 } std::lock_guard lock(m_mutex); const char* src = static_cast(m_mappedAddress) + offset; std::memcpy(buffer, src, size); return static_cast(size); } int VrShareMem::Lock(int timeout) { if (timeout == -1) { // 无限等待 m_mutex.lock(); return SUCCESS; } else { // 有超时的锁定 auto timeoutDuration = std::chrono::milliseconds(timeout); if (m_mutex.try_lock_for(timeoutDuration)) { return SUCCESS; // 成功 } else { return ERR_CODE(SHAREMEM_ERR_TIMEOUT); // 超时 } } } int VrShareMem::Unlock() { m_mutex.unlock(); return SUCCESS; } std::string VrShareMem::GetPlatformName(const std::string& name) const { #ifdef _WIN32 // Windows 文件映射对象名称 return "Global\\VrShareMem_" + name; #else // POSIX 共享内存名称,必须以 / 开头 return "/VrShareMem_" + name; #endif } bool VrShareMem::CheckBounds(size_t offset, size_t size) const { return (offset < m_size) && (offset + size <= m_size); } // 导出函数实现 IVrShareMem* CreateShareMemInstance() { return new VrShareMem(); } void DestroyShareMemInstance(IVrShareMem* instance) { delete instance; }