本题主要针对Linux平台编译的共享库(.so文件)。下次启动依赖于它的程序时,是否会自动加载新的库文件?如果没有,是否有不同的方法来实现这种无声的、独立的库更新?
3 回答
如果您删除然后重新创建相同的文件,许多基于 Unix 的操作系统具有允许此类内容的文件系统。据 Vlad Lazarenko 和我所知,Windows 和 DOS 是唯一不能做到这一点的操作系统。
只要打开一个文件,它就会一直保存到不需要它为止。当你删除它时,它在 fs 中是不可见的,但它仍然存在。它适用于所有类型的文件。
但是您可能需要 root 权限才能在库上执行此操作。您应该注意多个库之间的同步和依赖关系。您可以快速将 h 运行到 liba v1.0 只能与 libb v1.0 一起使用的情况,并且当您自动更新 liba 时,它会失败。
至少有两个著名的程序正在使用这种技术:apt和rpm。
编辑:如果您按照删除/重新创建模式更新您的库,那真的没有问题。您的旧但正在使用的库仍然存在于内存和磁盘中。如有必要,您的操作系统能够在磁盘上重新加载库的一部分。
只要所有使用它的程序都关闭,您的库仍然在磁盘上。甚至对于 libc 也是如此。这就是为什么当你更新你的 libc 时,你会被邀请重新启动几乎所有使用它的服务,以便将它们更新为新的二进制代码。
这也是为什么您可以热更新Linux系统而无需重新启动它多年的主要原因。
如果在 Linux 上,具有良好的 Linux 文件系统(例如 ext3 或 ext4 或 btrfs),您可以使用它更新libfoo.so
进程和程序(例如bar
)中的共享库(例如)(例如dlopen
-ing that libfoo.so
)
你最好有
- 将(2)旧的重命名
libfoo.so
为例如libfoo-old.so
- dlopen(3)的新版本
libfoo.so
- 到
dlsym
你想要的里面 - 也许dlclose(3)旧版本的旧版
dlopen
句柄;如果没有活动的调用框架指向,你只能这样做libfoo-old.so
(否则你的程序在返回到这样的调用框架时会崩溃)。 - 取消链接(2)如果
libfoo-old.so
需要
(您可以避免rename
,甚至可以unlink
使用 active dlopen
-ed 库;如果没有进一步的目录条目或进程文件描述符指向它,内核将删除它;我不建议这样做,例如为了简化潜在core
转储的调试)。
一个更简单但更“泄漏”的替代方案是 never dlclose
。在实践中,一个程序可以dlopen
有几十万*.so
,不用担心。请参阅我的旧manydl.c示例。
另请阅读有关动态软件更新的信息。
为了更好地理解 Linux 上的共享库,请阅读 Drepper 的论文如何编写共享库
你已经收到了一些很好的答案(尤其是 Coreen 的),所以我想我会问一个问题。你真的想这样做吗?除非您正在修复错误,并保证不会更改函数签名......最好提高版本号并部署新版本,不是吗?