Unloading/removing 来自进程的共享库

Unloading/removing shared libraries from process

所以这是我的问题。我在 VM 上有一个 Linux 程序 运行,它通过 dlopen 使用 OpenCL 来执行一些命令。大约在程序执行一半的时候它会休眠,并且在恢复时不能对 GPU 上的任何状态做出任何假设(事实上,驱动程序可能已经重新加载并且物理 GPU 可能已经改变)。在休眠之前调用 dlclose 并且这确实卸载了 OpenCL 内存区域(这是一件好事),但是 OpenCL 使用的库(在这种情况下为 cuda 和 nvidia 库)没有被卸载。因此,当程序恢复并尝试重新初始化所有内容时,事情失败了。

所以我正在寻找的是一种有效地 unlink/unload OpenCL 使用的共享库的方法,因此它可以正确地 "restart" 本身。请注意,进程本身可以在此转换期间根据需要暂停(停止),但可能不会被终止。
另外,假设我正在使用 root 访问权限并且对我可以访问的文件或多或少没有限制 modify/touch.

如果它们不卸载,这要么是因为某些东西保留了对它们的引用,要么是它们设置了 nodelete 标志,要么是因为 dlclose 的实现不支持卸载他们出于其他原因。请注意,不要求 dlclose 卸载任何东西:

An application writer may use dlclose() to make a statement of intent on the part of the process, but this statement does not create any requirement upon the implementation. When the symbol table handle is closed, the implementation may unload the executable object files that were loaded by dlopen() when the symbol table handle was opened and those that were loaded by dlsym() when using the symbol table handle identified by handle.

来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlclose.html

您遇到的问题是为什么在用户空间进程中加载​​图形驱动程序是一个完全糟糕的主意的症状,但解决这个问题既是技术挑战也是政治挑战(很多人反对修复它).

唯一的短期实用解决方案可能是将使用这些库的代码分解为一个单独的进程,您可以终止并重新启动它,并通过某种 IPC 机制与它对话,或者只是让您的整个程序序列化它的状态并在恢复时重新执行。

对于不太短期的实用解决方案,您可以尝试在加载的库上强制重新初始化序列,and/or强制卸载。

libdl 只是一个普通的库,您可以复制、修改和 link 而不是使用系统库。一种选择是禁用 RTLD_NODELETE 处理。另一个是给定库的 运行 DT_FINI/DT_INIT 序列。

dl_iterate_phdr,如果可用,可能无需修改 libdl 即可用于执行相同的操作。

使用 LD_DEBUG(如果支持)在 libdl and/or 中查找可能会阐明为什么它没有首先被卸载。