从库中动态加载类并在关闭库之后使用它
TL; DR:是否可以在运行时从库中加载类对象,关闭库然后将对象用作“普通”对象(关闭后)?从库中动态加载类并在关闭库之后使用它
我试图用某种“热插拔”功能实现插件系统。假设我的程序期望从其插件获取doSomething()
函数。我的想法是扫描文件系统以查找特定文件夹中的任何库,提取函数,然后关闭库(在使用函数之前!)。这样,监视器线程可以监视文件系统上的更改,并在发生更改时重置函数指针,从而插件可以“热插拔”。
我相信函数指针在我关闭库后就会失效(是这样吗?)。因此,我的想法是让库返回一个具有所需功能的对象的副本。在这种情况下,我会调用lib在关闭它之前创建该对象,并将该对象的副本保存在我的程序中。但是,由于对象可以使用库的其他对象/函数,因此我不确定这是否可行,因为这些对象/函数将不可用,是否它们?
您不能复制对象并关闭库,因为只有数据,而不是这些对象的代码被复制。而不是OS将库的代码加载到内存中,所有的函数指针都指向这个内存区域。如果操作系统卸载了库,会怎么样?
你可以实现这样的东西。您可以拥有一个包含指向当前加载的实现的指针的代理对象。如果检测到新库,则可以加载新库,创建新实现的实例,删除旧实例,关闭旧库。通过这种方式实现“热插拔”机制,避免共享库代码出现问题。
如果您选择了第2项中描述的方式,请注意并发性问题(如果在删除旧实现时但在指针更改之前计划另一个线程,那该怎么办?)。的
嘿,所以我想,dlopen/loadLibrary不会锁定库(导致消息如“文件X被程序Y使用”)?一旦lib被加载,整个代码/数据就在内存中,并且没有引用剩下的实际文件? – user1228633
@ user1228633当dlopen/loadLibrary将库加载到内存中时,库文件中的代码用于虚拟内存机制。如果有少量空闲的物理内存,操作系统可以从包含库代码的内存中卸载一些页面。但是,如果再次使用库中的代码,操作系统将从文件中读取库的未加载部分并将其加载回去。当然,如果图书馆没有关闭,这也是有效的。 –
@ user1228633当操作系统将库加载到内存中时,库使用的内存用于全局数据和代码。您创建的对象数据将放置在内存的其他部分,而所有函数指针都将指向专用于加载库的内存块。 –
对象是数据而不是代码。对象的副本是数据的副本,但它仍然指向原始代码。一旦你卸载了一个动态库,它的代码就从内存中消失了,并且任何仍然引用该代码的对象(即库提供的类型)都会在它们被要求执行成员函数时遇到麻烦(比如作为析构函数)。
所以不,不可能卸载一个库并继续使用它的代码。
但是,更积极的一点是,它*可能会加载一个库,使用它,一旦所有工作完成并删除所有相关对象,然后卸载库。我不明白为什么你想要什么就意味着你在使用它之前卸载了库,这样可能对你有用。 –
可能重复的[在存储器中复制的函数并执行它(http://stackoverflow.com/questions/4546071/copy-a-function-in-memory-and-execute-it) – Vality
我认为这是有效的问他是否可以将函数的代码复制到他自己的程序的内存中,这样他就不必使用系统链接器,有效地编写他自己的具有更多功能的链接器...... – Vality
不是真的在我看来,但感谢链接!由于我不知道插件的复杂程度有多复杂,所以我不知道究竟我需要加载到内存中以及它是如何构建的。 – user1228633