以下是对 ShareMemoryPubManager::CreateShm
函数的详细解读,结合代码逻辑和 Windows 共享内存机制分析:
该函数用于创建并映射一个共享内存区域,将其封装到自定义结构体 SwathShareMemory
中,并存储到成员变量 m_shmQueue
中。核心步骤包括:
shm_prefix
和 shm_id
生成唯一标识。CreateFileMapping
创建共享内存。MapViewOfFile
获取指向共享内存的指针。SwathShareMemory
结构体。std::string shm_name = shm_prefix + std::to_string(shm_id) + ".shm";
_bstr_t t = shm_name.c_str(); // 转换为宽字符
wchar_t *pwchar = (wchar_t *)t;
std::wstring result = pwchar; // 最终名称(Windows API 需宽字符)
LPCWSTR
)。shm_prefix
包含非 ASCII 字符,转换可能乱码。建议显式使用 std::wstring
避免转换1。DWORD dwMaximumSizeHigh = 0;
DWORD dwMaximumSizeLow = (DWORD)shm_size;
if (shm_size > 0xFFFFFFFF) { // 0xFFFFFFFF = 4GB
dwMaximumSizeLow = 0xFFFFFFFF;
dwMaximumSizeHigh = shm_size >> 32; // 取高 32 位
}
CreateFileMapping
要求将 64 位大小拆分为两个 32 位参数(DWORD
)。HANDLE shm_fd = CreateFileMapping(
INVALID_HANDLE_VALUE, // 使用系统分页文件(非物理文件)
NULL, // 默认安全属性
PAGE_READWRITE, // 读写权限
dwMaximumSizeHigh, // 内存大小(高 32 位)
dwMaximumSizeLow, // 内存大小(低 32 位)
result.c_str() // 共享内存名称
);
INVALID_HANDLE_VALUE
:表示共享内存由系统分页文件支持,而非磁盘文件。PAGE_READWRITE
:允许读写访问。NULL
表示失败(需用 GetLastError()
获取详细错误码)4。char *shm_data = (char*)MapViewOfFile(
shm_fd, // 文件映射对象句柄
FILE_MAP_READ | FILE_MAP_WRITE, // 读写权限
0, 0, // 映射偏移量(从文件头开始)
0 // 映射全部大小
);
CloseHandle(shm_fd)
并返回错误。SwathShareMemory shm;
shm.m_handle = shm_fd; // 文件映射句柄
shm.m_ptr = shm_data; // 共享内存指针
shm.m_name = result; // 共享内存名称
shm.m_status = ShareMemoryStatus::kProcessDone; // 状态标记
resetFreeFlag(&shm); // 初始化状态标志(自定义函数)
resetFrameFlag(&shm); // 同上
m_shmQueue[shm_id] = std::move(shm); // 存储到队列
resetFreeFlag
和 resetFrameFlag
可能是初始化共享内存头部状态(未提供实现)。std::move
避免复制开销。MapViewOfFile
失败,已正确关闭句柄 shm_fd
。shm_fd
和 shm_data
(需在类析构函数中添加 UnmapViewOfFile
和 CloseHandle
)。m_shmQueue
的写操作未加锁,多线程并发调用可能导致竞争。shm_name
可访问同一共享内存,但若名称全局不唯一,可能意外覆盖。// 析构函数中释放资源
ShareMemoryPubManager::~ShareMemoryPubManager() {
for (auto& [id, shm] : m_shmQueue) {
UnmapViewOfFile(shm.m_ptr);
CloseHandle(shm.m_handle);
}
}
// 线程安全:访问 m_shmQueue 时加锁
std::mutex mtx;
mtx.lock();
m_shmQueue[shm_id] = std::move(shm);
mtx.unlock();
阶段 | 操作 | API/操作 |
---|---|---|
创建 | 生成文件映射对象 | CreateFileMapping |
映射 | 关联进程地址空间 | MapViewOfFile |
使用 | 读写数据 | 通过 shm_data 指针访问 |
释放 | 解除映射并关闭句柄 | UnmapViewOfFile + CloseHandle |
bool ShareMemoryPubManager::CreateShm(size_t shm_id, size_t shm_size, const std::string &shm_prefix)
{
std::string shm_name = shm_prefix + std::to_string(shm_id) + ".shm";
_bstr_t t = shm_name.c_str();
wchar_t *pwchar = (wchar_t *)t;
std::wstring result = pwchar;
DWORD dwMaximumSizeHigh = 0;
DWORD dwMaximumSizeLow = (DWORD)shm_size;
if (shm_size > 0xFFFFFFFF)
{
dwMaximumSizeLow = 0xFFFFFFFF;
dwMaximumSizeHigh = shm_size >> 32;
}
_length = shm_size;
HANDLE shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE, // 使用无效句柄
NULL, // 安全性默认
PAGE_READWRITE, // 读写权限
dwMaximumSizeHigh, // 高位DWORD
dwMaximumSizeLow, // 地位DWORD
result.c_str() // 共享内存名称
);
if (shm_fd == NULL)
{
cout << "创建共享内存失败!" << endl;
return false;
}
char *shm_data = (char *)MapViewOfFile(shm_fd, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (shm_data == NULL)
{
CloseHandle(shm_fd);
cout << "映射共享内存失败!" << endl;
return false;
}
SwathShareMemory shm;
shm.m_handle = shm_fd;
shm.m_swathID = -1;
shm.m_ptr = shm_data;
shm.m_name = result;
shm.m_status = ShareMemoryStatus::kProcessDone;
resetFreeFlag(&shm);
resetFrameFlag(&shm);
m_shmQueue[shm_id] = std::move(shm);
return true;
}