请选择 进入手机版 | 继续访问电脑版
快捷导航
本帖最后由 李腾杰 于 2017-12-10 18:19 编辑

服务器更新:
现在,服务器已经具有文件传输功能,那么把文件传输过去后 如何在运行时进行替换
经了解,在Linux下可在运行状态下进行动态链接库的替换,经查阅,试验,步骤及结果如下

首选,了解一下 inode
在linux中,每一个文件都有一个inode节点,包含了文件的元信息,每一个inode节点都有一个inode编码,操作系统通过这个编码来识别不同的文件。
每次系统根据inode的信息来查找文件数据所在的block(块),来读取数据。
inode包含信息为:
  • 文件的字节数
  • 文件拥有者的User ID
  • 文件的Group ID
  • 文件的读、写、执行权限
  • 文件的时间戳,ctime, mtime 和 atime
  • 链接数,即有多少文件名指向这个inode
  • 文件数据block的位置


之后根据网上的其他帖子进行了一波测试:
首选 建立了如下文件
new.c  /  old.c:
  1. #include "libtest.h"
  2. #include <stdio.h>

  3. void foo()
  4. {
  5.         printf("old.so test\n");//printf("new.so test\n");
  6. }
复制代码
test.c
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include "libtest.h"

  4. int main(int argc, char const *argv[])
  5. {
  6.         loop:

  7.                 foo();
  8.                 sleep(1);
  9.                 goto loop;

  10.         return 0;
  11. }
复制代码

之后将old.c/new.c分别编译成.so库,
注意so文件名字一定要为 libxxx.so
  1. gcc old.c -fPIC -shared -o libtest.so

  2. gcc new.c -fPIC -shared -o libnew.so
复制代码
将libtest.so导入到“LD_LIBRARY_PATH”中,否则会找不到so文件
  1. LD_LIBRARY_PATH=/disk2/proj/test_so_171210:$LD_LIBRARY_PAT
复制代码

将test.c与old.c编译的so文件链接编译成可执行文件
  1. gcc test.c -L. -ltest -o test
复制代码
“-L.”表示so文件在当前目录下    “-ltest”表示链接到libtest.so文件,即“-lxxx”表示链接到libxxx.so文件

最后文件如下:


之后进行指令的测试

首先执行可执行程序./test,在运行状态下,使用“cp”指令,将newlib.so的内容复制到libtest.so中,发现程序停止运行,并报出错误。
之后重新运行./test,发现程序运行结果为new.c中的函数



之后进行"rm+cp"和“mv+cp”的指令测试

重新将libtest.so的内容换为old.c
先执行test文件,之后输入指令




发现程序并未停止,且输出仍为old中的函数内容

之后停止并重新运行后,发现程序已经被替换new中的函数

经查阅,导致上面的原因为inode的作用
当执行“cp”指令后,文件的属性发生了变化,导致了inode发生了变化,程序停止运行,出现segmentation fault的错误。
如果先删除目标文件,新的文件的inode已经发生了变化,而原inode信息并没有发生改变,它被内核所锁定,直到内核释放对它的引用。
使用mv只会修改文件名,并不会改变inode,新创建的文件会使用新的inode,这两种方法替换正在运行的程序都不会出错。

所以要在程序运行时,进行so库的替换,就必须使用“rm+cp”或“mv+cp”指令,
虽然这连个指令。将库的内容替换掉,但是,程序运行状态时,仍然链接的是原来的so文件,所以替换后扔需要重启,在程序结束时释放旧的文件,之后重启后链接新的数据。

所以,初步思想如下:
需要有一个独立的更新程序(相当于一个插件),
在需要更新时,通过文件传输传输文件,将动态链接库替换掉(执行脚本),
之后通过更新程序运行脚本将主服务器程序重新启动,释放旧的so库,更新成新的文件

另外:
如果这个更新程序作为一个类似启动端的程序,更新替换后再启动,可进行更新
如果可以同时独立运行在后台,当有更新后下载文件,更新完成后,提示用户重启更新成功,之后重启后完成,就为热更新,体验则会更加好

即这个独立的更新程序更新时的操作在后台运行,等待重启之后完全完成。即为热更新(个人理解)。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Connecting & Messaging from Any.

共 4 个关于本帖的回复 最后回复于 2017-12-11 10:04

chinmel 版主 发表于 2017-12-10 21:23:59 from Mobile | 显示全部楼层
以上思路确实可行。我提供另一个方向,可能和这个是相同的结果,但值得一试:一个程序,可以在编译链接时,指定引用一个so,如楼主贴所示。
也可以,不在编译链接时指定。
应用程序中,需要使用系统API来引用so,具体操作,参见dlopen一套。
注意,使用dlopen,需要在链接时,增加一个-ldl选项,即包含dl库。
dl即dynamicLoading简写。
重点测试,如果使用dlopen,是否可以使得应用程序,不用重启就能直接使用更新后的so?
Connecting & Messaging from Any.
举报 使用道具
李腾杰 中级会员 发表于 2017-12-11 09:38:31 | 显示全部楼层
chinmel 发表于 2017-12-10 21:23
以上思路确实可行。我提供另一个方向,可能和这个是相同的结果,但值得一试:一个程序,可以在编译链接时, ...

可以,我找时间测试一下
Connecting & Messaging from Any.
举报 使用道具
anymsg_renzong 版主 发表于 2017-12-11 09:48:35 | 显示全部楼层
在linux下运行 ??
Connecting & Messaging from Any.
举报 使用道具
李腾杰 中级会员 发表于 2017-12-11 10:04:33 | 显示全部楼层

是的,大佬
Connecting & Messaging from Any.
举报 使用道具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

推荐板块

精彩推荐

热门排行

明星用户

手机版|小黑屋|AnyMSG ( ©AnyMSG 2009 - 2017 · ICP备16009991号 )

GMT+8, 2019-4-25 22:48