两个 exe 是不是可以从 DLL 访问内存中的同一个对象?
Posted
技术标签:
【中文标题】两个 exe 是不是可以从 DLL 访问内存中的同一个对象?【英文标题】:Is it possible for two exe's to access the same object in memory from a DLL?两个 exe 是否可以从 DLL 访问内存中的同一个对象? 【发布时间】:2021-11-25 06:00:31 【问题描述】:我有一个要求,两个独立的应用程序需要访问和修改 DLL 中包含的对象(应用程序的所有控制逻辑都是用 C++ 编写的,并从 DLL 运行)。 UI exe(具有最少的逻辑,用 C++ 编写)使用此 DLL 并与主控制逻辑 DLL 交互。我希望添加一个额外的 exe(用 C# 编写)来运行多个基于 Web 的服务,这些服务也需要访问 DLL 中包含的相同对象。
【问题讨论】:
只要有足够的时间、金钱和轻子,一切皆有可能。 当你说“同一个对象”时,他们是需要看到彼此的变化,还是专门独立工作? DLL 包含一个非常大的应用程序,exe 可以通过 pub/sub 代理与之交互。我需要从两个 exe 访问该 Broker 对象,以便它们可以访问相同的数据。 您的问题是关于如何在两个应用程序之间共享数据?如果是这样,共享内存可能是一种方法,但有很多方法可以做到这一点(队列、文件、API 等)。您不能通过加载通用 dll 来共享数据。 【参考方案1】:是的,它被称为共享内存。 dll 需要调用CreateFileMapping 来分配要共享的内存区域。然后调用MapViewOfFile 将文件映射到内存中。然后多个进程可以通过它的名字访问这个映射的内存。
【讨论】:
我已经对此进行了研究,但我的理解是您不能简单地将整个对象映射到共享内存,对吗?该对象生成的数据会不断更新,需要两个应用程序同时读取。 从技术上讲,如果这是您真正想做的事情,您可以将整个对象映射到共享内存中,但这会变得有点复杂,因为您必须了解 Windows 可移植文件格式,并且这种技术通常是用于“阴暗”的应用程序。但我认为你想要做的只是加载一个 dll 并让 dll 映射内存。这也可以在没有 dll 的情况下完成,但本质上一个进程不能从另一个进程加载相同的 dll 实例是两个单独的实例 但是任何进程或dll映射的共享内存区域都可以被其他进程/dll访问【参考方案2】:这不是关于 c++ 本身的问题,而是关于您的操作系统如何处理共享库的问题。根据我在 Solaris 系统上查看应用程序加载器行为的经验,答案是否定的。我认为 Solaris 的行为紧随其后的是 Windows、Linux 等,但我想可能会有一个奇特的操作系统确实需要你要求(我在看你 QNX)。
基本上,如果您创建一个全局变量,假设:
int foo = 5;
编译你的 dll 并分析你的 dll 的内容,你会看到 foo 包含在一些读/写数据部分。
由于该部分是读/写的,因此当 exe 启动并加载 dll 时,操作系统将为该 exe 创建该部分的副本。现在您的 exe 可以将值更改为它想要的任何 int,但它只会更改其 foo 的副本。
如果您启动另一个 exe,它也会加载 dll 并获得该部分的副本。该 exe 将拥有自己的 foo 副本,并且最初将设置为 5。
只读部分的行为不同,所以如果你要定义 foo 如下:
static const int foo = 5;
它最终会出现在 dll 的只读部分中,并且每个 exe 都会引用内存中的同一个 foo。它不允许你做你想做的事情,但很高兴知道它可以节省内存。一个好的经验法则是尽可能制作 static
和 const
。
【讨论】:
这是正确的,但是进程可以访问共享内存,这实际上并不是两个共享同一个 dll 实例的进程。但这是一种解决方法 您会推荐任何替代方法吗? - 是否可以在同一进程中启动 2 个 exe? - 子进程是否允许任何程度的内存访问继承? - 将第二个 exe(当前为后台服务)设为 dll 并从主 dll 加载它是不是一个好主意 @ScottFraser 根据我收集的信息,您在 DLL 中存储了一些复杂的逻辑,您希望在 DLL 中初始化一个对象并将该对象用作多个子进程的服务。为什么不将对象包装在 API 周围并进行 RPC 调用以与 API 交互?看看 gRPC grpc.io.以上是关于两个 exe 是不是可以从 DLL 访问内存中的同一个对象?的主要内容,如果未能解决你的问题,请参考以下文章