3

本题主要针对Linux平台编译的共享库(.so文件)。下次启动依赖于它的程序时,是否会自动加载新的库文件?如果没有,是否有不同的方法来实现这种无声的、独立的库更新?

4

3 回答 3

6

如果您删除然后重新创建相同的文件,许多基于 Unix 的操作系统具有允许此类内容的文件系统。据 Vlad Lazarenko 和我所知,Windows 和 DOS 是唯一不能做到这一点的操作系统。

只要打开一个文件,它就会一直保存到不需要它为止。当你删除它时,它在 fs 中是不可见的,但它仍然存在。它适用于所有类型的文件。

但是您可能需要 root 权限才能在库上执行此操作。您应该注意多个库之间的同步和依赖关系。您可以快速将 h 运行到 liba v1.0 只能与 libb v1.0 一起使用的情况,并且当您自动更新 liba 时,它会失败。

至少有两个著名的程序正在使用这种技术:aptrpm

编辑:如果您按照删除/重新创建模式更新您的库,那真的没有问题。您的旧但正在使用的库仍然存在于内存和磁盘中。如有必要,您的操作系统能够在磁盘上重新加载库的一部分。

只要所有使用它的程序都关闭,您的库仍然在磁盘上。甚至对于 libc 也是如此。这就是为什么当你更新你的 libc 时,你会被邀请重新启动几乎所有使用它的服务,以便将它们更新为新的二进制代码。

这也是为什么您可以热更新Linux系统而无需重新启动它多年的主要原因。

于 2012-04-05T19:32:53.853 回答
4

如果在 Linux 上,具有良好的 Linux 文件系统(例如 ext3 或 ext4 或 btrfs),您可以使用它更新libfoo.so进程和程序(例如bar)中的共享库(例如)(例如dlopen-ing that libfoo.so

你最好有

  1. (2)旧的重命名libfoo.so为例如libfoo-old.so
  2. dlopen(3)的新版本libfoo.so
  3. dlsym你想要的里面
  4. 也许dlclose(3)旧版本的旧版dlopen句柄;如果没有活动的调用框架指向,你只能这样做libfoo-old.so(否则你的程序在返回到这样的调用框架时会崩溃)。
  5. 取消链接(2)如果libfoo-old.so需要

(您可以避免rename,甚至可以unlink使用 active dlopen-ed 库;如果没有进一步的目录条目或进程文件描述符指向它,内核将删除它;我不建议这样做,例如为了简化潜​​在core转储的调试)。

一个更简单但更“泄漏”的替代方案是 never dlclose。在实践中,一个程序可以dlopen有几十万*.so,不用担心。请参阅我的旧manydl.c示例。

另请阅读有关动态软件更新的信息。

为了更好地理解 Linux 上的共享库,请阅读 Drepper 的论文如何编写共享库

于 2012-04-05T20:30:39.520 回答
1

你已经收到了一些很好的答案(尤其是 Coreen 的),所以我想我会问一个问题。你真的想这样做吗?除非您正在修复错误,并保证不会更改函数签名......最好提高版本号并部署新版本,不是吗?

于 2012-04-05T19:41:01.053 回答