9

如果我的进程正在加载 .so 库并且如果有新版本的库可用,是否可以在不重启进程的情况下切换到新库?或者答案取决于库中现有函数之一是否有参数更改?

我在一个相当大的系统中工作,该系统运行 100 个进程,每个进程加载 10 个库。这些库提供特定的功能,由不同的团队提供。因此,当库中的一个更改(可以说是错误修复)时,理想的做法是在不影响运行过程的情况下在后台发布它。可能吗 ?

编辑谢谢!在我的情况下,当一个新库可用时,所有正在运行的进程都必须开始使用它。让他们使用旧版本运行并稍后再选择新版本是不可取的。所以看起来更安全的选择是重新加载进程。

4

8 回答 8

6

一种有趣的技术,虽然它在检查点恢复步骤中有些容易失败,但它是进行不可见的重新启动。

您的服务器进程或任何其他进程都将其所有必要信息保存到磁盘文件中。包括文件描述符编号和当前状态。然后,服务器进程执行exec系统调用来执行自身,替换自身的当前版本。然后它从磁盘文件中读取它的状态并继续提供它的文件描述符,就好像什么都没发生一样。

如果一切顺利,重启是不可见的,新进程正在使用所有更新的库。

于 2012-04-03T23:46:10.213 回答
6

您无法在进程运行的情况下即时升级链接库。您甚至可以尝试,但如果您成功(并且您不会因“文本文件正在使用”错误消息而失败),您将不得不重新启动该过程以使其将新库映射到内存中。

您可以使用 lsof 命令检查链接了哪些库(运行时或链接时):

lsof -p <process_pid> | grep ' mem '
于 2012-04-03T21:25:16.603 回答
4

至少,您必须确保库的接口不会在版本之间发生变化。如果可以确定,那么我会尝试使用 dlopen/dlsym 动态加载库,看看 dlclose 是否允许您重新加载。

我自己从来没有做过这些,但这是我首先要追求的道路。如果你这样走,你能公布结果吗?

于 2012-04-04T12:14:03.927 回答
4

Linux提供了几种动态加载器接口,进程可以在运行时加载动态库。linux 提供的 dlopen 和 dlsysm 可以解决你的问题。

于 2013-03-18T09:22:32.283 回答
1

如果您希望库定期更改,并且希望保持正常运行,我认为应该重新设计您的系统,以便这些库实际上成为松散耦合的组件(例如服务)。

话虽如此,我对这个问题的回答是肯定的:在某些情况下,可以在不重新启动进程的情况下更新共享库。在大多数情况下,我认为这是不可能的,例如当你的库的 API 发生变化时,当你的数据段的排列发生变化时,当库维护内部线程时。名单很长。

对于代码的非常小的错误修复,您仍然可以使用ptrace写入进程内存空间,然后从那里重做/lib/ld-linux.so在动态链接方面所做的工作。老实说,这是一项极其复杂的活动。

于 2012-04-03T22:28:07.710 回答
0

有时您可以升级正在使用的 .so,有时则不能。这主要取决于您如何尝试,还取决于您运行的内核的安全保证。

不要这样做: cat new.so > old.so ...因为最终,您的进程可能会尝试请求页面某些内容,并发现它不再位于正确的位置。这是一个问题,因为东西的地址可能会改变,它仍然是同一个inode;你只是覆盖文件中的字节。

但是,如果你: mv new.so old.so 在大多数系统上你会没事的,因为你正在运行的进程可以为旧库保留一个现在未命名的 inode,而你的进程的新调用会得到新文件。但是,有些内核不喜欢让你 mv 一个正在使用的 .so,也许是出于谨慎,也许是为了它们自己的简单性。

于 2012-04-03T22:05:26.307 回答
0

ldd 进程的二进制文件是找出答案的一种方法。尽管理论上可行,但不建议修改正在运行的进程,尽管我确信存在一些实用程序,例如可以修改正在运行的 linux 内核的 ksplice。

您可以简单地升级并且运行过程将继续使用旧版本,并在重新启动时选择新版本,假设您的包管理系统很好并且知道可以安装什么。

于 2012-04-03T20:57:31.053 回答
0

您可能想了解共享库版本控制和 ld-h选项。

一种使用方法如下:

您在构建系统中维护一个版本计数器。您使用以下方式构建共享库:

ld ..... -h mylibrary.so.$VERSION

但是,你把它放在你的开发树的库中,就像 plain 一样mylibrary.so。(还有一个涉及将整个 .so 放入 .a 文件的技巧)。

现在,在运行时,使用该库的进程会查找完整版本的名称。要推出新版本,只需新版本添加到图片中即可。运行与旧版本链接的程序继续使用它。当程序重新链接并针对新程序进行测试时,您会推出新的可执行文件。

于 2012-04-03T21:07:44.443 回答