更新共享库,无需重新启动过程(Update shared libraries without res

2019-06-23 09:20发布

如果我的进程加载.so库,如果库的新版本可用,才有可能切换到新的库而不进行重启进程? 或答案取决于之类的东西是否有参数的更改库中的现有功能之一?

我在它运行的过程100S和图书馆的每10秒加载一个相当大的系统工作。 该库提供特定的功能,并通过不同的团队提供。 所以,当图书馆的变化之一(一个bug修复,您说的)理想的事情是将它发布在引擎罩而不影响正在运行的进程。 可能吗 ?

编辑感谢! 在我的情况下,当一个新的图书馆可用的所有正在运行的进程必须开始使用它。 它不是选择让他们与老版本上运行,后来接了新的。 所以看起来更安全的选择是刚刚重装的过程。

Answer 1:

你不能上运行的进程动态升级链接库。 你甚至可以尝试,但如果你赢得成功(你会不会失败与“文本文件正在使用”错误消息),你必须重新启动该进程,使其映射新的库到内存中。

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

lsof -p <process_pid> | grep ' mem '


Answer 2:

一个有趣的技术,尽管它是有点容易在检查点故障恢复的步骤,就是做一个无形的重启。

你的服务器进程或不管它是什么,保存其所有必要信息到磁盘文件。 包括文件描述符数字和当前状态。 然后,服务器进程执行的exec系统调用执行本身,免去自身的当前版本。 然后,它从磁盘文件中读取它的状态,并恢复若无其事服务的文件描述符。

如果一切顺利,重启是无形的和新的进程正在使用的所有更新的库。



Answer 3:

最起码,你必须确保该库的接口不版本之间切换。 如果是有保证的,那么我会尝试寻找到动态加载使用dlopen / dlsym进行的库,看看是否dlclose可以让你重新加载。

我从来没有做过任何的这个自己,但这是我第一次追求的路径。 如果你走这条路,你可以公布结果?



Answer 4:

Linux提供了动态加载程序接口,并运行时,过程可以加载动态图书馆的。 执行dlopen和Linux所提供的dlsysm可以解决你的问题。



Answer 5:

如果你希望libaries来改变相当定期的,你希望保持正常运行时间,我认为你的系统应该进行重新设计,使这样的图书馆居然成为松散耦合的组件(如服务)。

说了这么多,我的问题的答案是肯定的:在某些情况下, 可以更新共享库,而无需重新启动的过程。 在大多数情况下,我希望它是不可能的,例如当你的库变化的API,当你的数据段变化的结构中,当库维护内螺纹。 这份名单是很长。

对于非常小的bug修复代码,你仍然可以使用ptrace的写入进程的内存空间,并从那里重做什么/lib/ld-linux.so确实在动态链接的条款。 老实说,这是一个非常复杂的活动。



Answer 6:

LDD的过程的二进制是找出一种方式。 虽然在理论上是可能的,这是不可取的与正在运行的进程进行修补,但我相信公用事业存在诸如Ksplice的是与正在运行的Linux内核修补。

你可以简单地升级和运行过程中会继续使用旧版本,并搭载全新的版本,重新启动时,假设你的软件包管理系统是好的,知道什么是comptible安装。



Answer 7:

你可能想了解共享库版本和LD -h选项。

使用它的方法之一是如下:

你保持你的编译系统版本计数器。 您建立与共享库:

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

但是,你把它放在你的开发树的lib的只是普通的mylibrary.so 。 (还有涉及把整个的.so到某文件黑客攻击)。

现在,在运行时,处理使用图书馆的外观为全版本的名称。 要推出一个新版本,你只需要添加新版本的图片。 对旧版本的链接运行的程序继续使用它。 由于程序重新链接,并针对新的测试,你推出新的可执行文件。



Answer 8:

有时候,你可以升级使用中的。所以,有时你不能。 这主要取决于你如何尝试做到这一点,同时也对你在运行的内核的安全保证。

不这样做:猫new.so> old.so ......因为最终,你的进程可能会试图要求页的东西,发现它不是在正确的位置了。 这是一个问题,因为物联网的地址可能改变,它仍然是相同的inode; 你只是覆盖文件中的字节。

但是,如果您:MV new.so old.so你会在大多数系统OK,因为你正在运行的进程可不放的老图书馆现在命名的索引节点,而你的流程的新的调用得到新的文件。 但一些内核不喜欢让你MV的使用中。所以,或许是出于谨慎,也许是对自己的简单性。



文章来源: Update shared libraries without restarting processes