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