DLL互斥体——一个例子

3

可能重复:
DLL线程安全性

您好

我在MS VS C++ Express中编写了一个DLL文件,同时在多个客户端应用程序中加载它,它与其他已加载的DLL实例使用共享内存。让我们假设该DLL看起来像这样:

#include stdafx.h  
#pragma data_seg (".TEST")  
//Shared variables  
#pragma data_seg ()  
#pragma comment(linker, "/section:.TEST,RWS")  
_DLLAPI void __stdcall doCalc()  
{  
//Do critical stuff  
}

如果同时有两个或更多客户端调用doCalc,系统将崩溃。 我该如何创建一个互斥锁来“阻塞”其他调用,如果该函数已经被调用了? 请给出一个示例,因为我已经花了过去两个小时在网上寻找一个像样的示例 ;) 提前致谢。
3个回答

4
每个进程的代码:
// At the start of every process
HANDLE sharedMemoryMutex = CreateMutex(NULL, FALSE, "My shared memory mutex");

// When you want to access shared memory:
DWORD dwWaitResult = WaitForSingleObject(sharedMemoryMutex, INFINITE);

if (dwWaitResult == WAIT_OBJECT_0 || dwWaitResult == WAIT_ABANDONED)
{
   if (dwWaitResult == WAIT_ABANDONED)
   {
      // Shared memory is maybe in inconsistent state because other program
      // crashed while holding the mutex. Check the memory for consistency
      ...
   }

   // Access your shared memory
   ...

   // After this line other processes can access shared memory
   ReleaseMutex(sharedMemoryMutex);
}

你也需要确保以下两点:1)其他进程(在其他用户的上下文中运行)获得相同的互斥体;2)其他进程也可以访问该互斥体。实现方法是:1)在互斥体名称前使用“Global\”前缀;2)在创建互斥体时指定适当的安全描述符。 - villintehaspam
@villintehaspam,你的断言是正确的,但我怀疑它们是否适用于OP的情况。 - Dialecticus
你可能是对的 - 我只是认为这些信息应该提供给 OP,以便他们可以做出知情决策是否关心这个问题。 - villintehaspam
谢谢您的回答,我已经根据您的答案修改了代码,您能否看一下并告诉我它是否有效? - sigvardsen
@sigvardsen,嗯,忽略你代码中有一些奇怪的...点,它看起来对我来说是有效的 :-)。只有你知道它是否实际有效。运行并测试它。如果出现问题,请提出另一个问题,说明出了什么问题,并不要编辑此问题以使其成为另一个问题。 - Dialecticus

0
你可以从MSDN 这里开始使用“使用互斥对象”示例。为了让互斥对象在进程之间共享,你需要更改CreateMutex调用以使用名称。

您需要确保以下两点:1)其他进程(在其他用户的上下文中运行)获得相同的互斥量;2)其他进程也可以访问该互斥量。实现方法是:1)在互斥量名称前使用“Global\”前缀;2)在创建互斥量时指定适当的安全描述符。 - villintehaspam
如果他在不同用户运行的进程之间共享了可写内存映射,那么他就存在一个巨大的安全漏洞。依赖于全局命名空间中的互斥锁也是一个巨大的安全漏洞,因为它可以轻易地被攻击者占用。 - Michael
正确的做法是在互斥量和文件映射中使用相同的名称作用域,而且两者都应该是会话本地的。 - Ben Voigt

0

你应该使用共享文件映射对象来创建共享内存,而不是使用链接器将一个部分标记为共享。相对容易的管理方法是将所有共享变量放入单个struct中,然后将MapViewOfFile的返回值强制转换为指向此结构体的指针。

当然,在这个共享区域中不能有指针,但是你可以在进程之间交换索引信息(当然是指向共享区域中的数组)。

即使是链接器共享的部分也不能保证在所有进程中加载到相同的地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接