gpt4 book ai didi

c++ - 在 C++ 应用程序中安全地生成内存映射文件

转载 作者:太空狗 更新时间:2023-10-29 23:06:35 26 4
gpt4 key购买 nike

我有一个最初用 Visual C++ 6.0 构建的古老 C++ 应用程序,它使用一个非常复杂的共享内存 DLL 在大约 8 个 EXE 和 DLL 之间共享数据,这些 EXE 和 DLL 都有一个可以用一个或两个字典替换的值池以字符串为键,以记录为值。该应用程序是多线程和多进程的。共有三个主要的可执行文件读取和写入共享内存区域,其中几个可执行文件有 3 个或更多线程读取/写入或“排队”信息到这个池内存区域。大约几百个地方,__try__except 的结构化异常处理 (SEH) 用于过滤异常,并通过调整共享内存的大小来尝试处理访问冲突,它们位于由名为 CGMMF 的类管理的段中,这意味着可增长的内存映射文件。

此处显示了最突出的细节,因为我找不到任何有关所用技术或其安全性和适用性的完整文档来源。通过实验,我发现这个库在 1998 年的单核系统上运行得不是很好,它在运行 windows XP 的单核虚拟机上运行得很好,而在现代 2+ ghz multi 上它根本无法运行2013 年的核心 Windows 7 64 位系统。我正在尝试修复它或更换它。

#define ResAddrSpace(pvAddress, dwSize)  \
(m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE, &m_SecAttr, \
PAGE_READWRITE| SEC_RESERVE, 0, dwSize, m_szRegionName), \
(m_hFileMapRes == NULL) ? NULL : \
MapViewOfFileEx(m_hFileMapRes, FILE_MAP_ALL_ACCESS, 0, 0, dwSize, 0))


void CGmmf::Create(void)
{
DWORD dwMaxRgnSize;
if (Gsinf.dwAllocationGranularity == 0)
{
GetSystemInfo(&Gsinf);
}
m_dwFileSizeMax = RoundUp(m_dwFileSizeMax, Gsinf.dwAllocationGranularity);
m_dwFileGrowInc = RoundUp(m_dwFileGrowInc, Gsinf.dwAllocationGranularity);
dwMaxRgnSize = m_dwFileSizeMax + m_dwOverrunBuf;
m_pbFile = (PBYTE)ResAddrSpace(NULL, dwMaxRgnSize);
Adjust(m_dwFileSizeNow);
}

void CGmmf::Adjust(IN DWORD dwDiskFileNow)
{
int nThreadPriority;

__try
{
//
// Boost our thread's priority so that another thread is
// less likely to use the same address space while
// we're changing it.
//
nThreadPriority = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

//
// Restore the contents with the properly adjusted lengths
//
Construct(dwDiskFileNow);
}
__finally
{
//
// Make sure that we always restore our priority class and thread
// priority so that we do not continue to adversely affect other
// threads in the system.
//

SetThreadPriority(GetCurrentThread(), nThreadPriority);
}
}


void CGmmf::Construct(IN DWORD dwDiskFileNow)
{
DWORD dwDiskFileNew = RoundUp(dwDiskFileNow, m_dwFileGrowInc),
dwStatus = ERROR_SUCCESS;

PBYTE pbTemp;

if (dwDiskFileNew > 0)
{
//
// Grow the MMF by creating a new file-mapping object.
//
// use VirtualAlloc() here to commit
// the requested memory: VirtualAlloc will not fail
// even if the memory block is already committed:

pbTemp = (PBYTE)VirtualAlloc(m_pbFile,dwDiskFileNew,MEM_COMMIT,PAGE_READWRITE);

if(NULL == pbTemp)
{
LogError(GetLastError(), MEM_CREATE_MMF, m_szRegionName);

//
// File-mapping could not be created, the disk is
// probably full.
//
RaiseException(EXCEPTION_GMMF_DISKFULL,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}

//
// Check to see if our region has been corrupted
// by another thread.
//
if (pbTemp != m_pbFile)
{
RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
}
}

到目前为止,我替换它的选项包括尝试用 DCOM(进程外 COM)和 COM(进程 COM)替换所有共享内存内存映射文件的位置,并根据需要使用同步/互斥/临界区或其他线程安全结构来手动防止并发问题。

我想知道是否已经有一些线程安全的内存字典类型可以替换所有这些。即使上面的代码片段还不到这个古老的 shared-memory-library-for-visual-C++-6 代码的 1%,也有让我不寒而栗的事情。例如,提高线程优先级作为避免死锁、竞争条件和一般损坏的策略。也许这曾经使这段代码在 33 mhz 的 80486 CPU 上不再崩溃。 不寒而栗。

我的代码在 Visual C++ 6.0 中构建和运行,它的一个分支在 Visual C++ 2008 中运行,我可能会在 Visual C++ 2010 中运行它。我可以使用什么来提供字典语义,共享跨进程内存,稳定可靠?

更新 “字典”是指 Python 中已知的字典数据类型,在某些地方也称为“键/值存储”,在其他地方(如 C++ 标准库中) ),它被称为 std::map。讨论这个的 Boost 文档是 here.

最佳答案

听起来你应该看看Boost Interprocess .您可以使用它在共享内存中拥有类似 std::map 的对象等等。自从我上次使用它已经有好几年了,所以不能详细介绍,但是库文档很好并且有大量示例,它应该让你在 30 分钟内开始。

关于c++ - 在 C++ 应用程序中安全地生成内存映射文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15295579/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com