我有一个DLL,可能同时被多个应用程序调用。 此DLL内存映射文件。
我有两个问题:
1)每个应用程序都会创建自己的DLL实例,对吧? 因此,文件将多次进行内存映射
2)如果这是真的,我不明白这里发生了什么:
a)应用程序A调用DLL。 b)应用程序B调用DLL。 c)我退出应用程序A,DLL将取消映射文件。 d)应用程序B调用DLL,内存映射文件不再可用,并且调用失败。
我不明白这一点。 有人这样做吗?
谢谢。
答案 0 :(得分:3)
这是因为您对1)的假设是错误的。根据定义,dll是共享的;两个应用程序都使用相同的dll实例,因此当您在一个应用程序中释放该文件时,其他应用程序将无法使用该文件。
要解决您的问题,您应该实现一些引用计数机制,以便仅在没有进程使用它时取消映射文件。
修改:@sumeet是对的。每个进程都有自己的地址空间;当两个进程加载相同的dll时,它们可能共享其只读数据以提高效率,但是它们的可写数据对于每个进程都是本地的。然而,内存映射文件是一个内核对象,如信号量,管道和共享内存。因此,如果您在一个过程中取消映射,则为所有人取消映射。
Edit2 :来自MSDN(备注部分):
多个进程可以通过使用a共享同一文件的视图 单个共享文件映射对象或创建单独的文件映射 由同一文件支持的对象。单个文件映射对象可以 通过在进程中继承句柄来共享多个进程 创建,复制句柄或打开文件映射对象 按名字。有关更多信息,请参阅CreateProcess,DuplicateHandle 和OpenFileMapping函数。
[...]
文件映射对象的映射视图维护内部引用 对象和文件映射对象直到全部关闭 对它的引用已经发布。因此,要完全关闭文件 映射对象,应用程序必须取消映射文件的所有映射视图 通过调用UnmapViewOfFile映射对象并关闭文件映射 通过调用CloseHandle来处理对象句柄。可以调用这些函数 任何订单。
首先,从第一段开始,每个应用程序如何初始化视图?
从第二段开始,我收集到每个应用程序调用{{1}}和UnmapViewofFile
将释放对内存文件的所有引用,然后Windows将自动释放相关资源(即他保留引用计数,你不需要这样做)。
发布两个应用程序的内存映射初始化和关闭代码。