热替换so文件

www.zhaoch.top > 操作系统 > linux

发现nginx的动态模块无法热更新,于是研究了一下相关的问题。

代码准备

reload.c, 启动文件,用来模拟正在运行的程序,不断重建加载so.so文件

#include <dlfcn.h> #include <stdio.h>  typedef void (*F)();  int my_dlopen() {     void* h = dlopen("so.so", RTLD_NOW|RTLD_GLOBAL);     if (!h) {         fprintf(stderr, "%s\n", dlerror());         return 1;     }      F f = (F)dlsym(h, "action");     f();      return 0; }  int main(int argc, char const *argv[]) {     printf("start...\n");      while (1) {         printf("run\n");         if (my_dlopen() != 0) {             return 1;         }         sleep(2);     }      return 0; } 

so1.c 模拟其中一个so文件

#include <stdio.h>  void action() {     printf("11111111111111111\n"); } 

so2.c 模拟其中另一个so文件,接口相同,打印内容不同

#include <stdio.h>  void action() {     printf("222222222222222222222\n"); } 

编译

gcc reload.c -ldl -o reload gcc -fPIC -shared so1.c -o so1.so gcc -fPIC -shared so2.c -o so2.so 

注意

所有的实验需要 export LD_LIBRARY_PATH=./ 

第一次尝试,直接cp替换

先将 so1.so 设置成默认的 so文件

cp so1.so so.so 

启动程序, 然后执行 cp so2.so so.so

./reload  start... run 11111111111111111 run 11111111111111111 run 11111111111111111 run 11111111111111111  <-- 执行 cp so2.so so.so run [1]    38314 segmentation fault (core dumped)  ./reload 

程序直接崩溃

同时测试了下,rm so.so并不影响执行,但是停止程序再启动显示so.so: cannot open shared object file: No such file or directory 这个可能说明,so文件被打开一次后句柄并不会关闭,下次打开任然用这个句柄。只是重新读取文件。cp 改变文件内容,并不改变文件inode。

先rm再cp

cp so1.so so.so  ./reload start... run 11111111111111111 run 11111111111111111 run 11111111111111111 run 11111111111111111 run 11111111111111111  <-- rm so.so;cp so2.so so.so run 11111111111111111 run 11111111111111111 run 11111111111111111 

结果就是更新无效,猜想还是句柄没关闭的原因。rm的后,程序还指向原来的文件(这个文件外界看不到), cp产生了一个新的文件,程序根本没有理睬这个文件。

dlclose 再加载

在代码中加入 dlclose(h),如下:

int my_dlopen() {     void* h = dlopen("so.so", RTLD_NOW|RTLD_GLOBAL);     if (!h) {         fprintf(stderr, "%s\n", dlerror());         return 1;     }      F f = (F)dlsym(h, "action");     f();      dlclose(h); // <--      return 0; } 

这次可以了

./reload start... run 11111111111111111 run 11111111111111111 run 11111111111111111 run 11111111111111111   <-- cp so2.so so.so run 222222222222222222222 run 222222222222222222222 run 222222222222222222222 run 222222222222222222222 

说明确实时句柄的问题,这里涉及到linux inode的问题。每个文件都会对应一个inode, 内部都是按照inode来处理的,同一个文件名的不一定是同一个inode。一个文件只有在没有任何引用的时候才被删除,当程序打开一个so文件,这个文件就被引用了,即使外部删除这个文件,程序还是在使用这个so文件,这个文件只有在程序关闭时才被系统回收。cp过来时个全新的文件,只是文件名相同,inode并不相同,其实程序还是用着老的so文件。dlclose恰恰时关闭了这个文件,之后再次按文件名打开就是新的文件。

备注

看了下nginx的代码,貌似先dlopen之后再close旧的handle,这样是无法热更新的,不太清楚处于什么考虑。

The End

linux 热替换so文件的更多相关文章

  1. linux 批量替换所有文件中包含的字符串

    sed -i "s/原来字符串/新字符串/g" `grep 原来字符串 -rl .` 格式: sed -i "s/查找字段/替换字段/g" `grep 查找字段 ...

  2. linux批量替换指定文件夹中所有文件的指定内容

    命令:sed -i "s#https#http#g" `grep http -rl VEROMODA` 功能:用来替换当前目录VEROMODA文件夹及子文件夹中所有文件中的http ...

  3. Linux命令行批量替换多文件中的字符串【转】

    Linux命令行批量替换多文件中的字符串[转自百度文库] 一种是Mahuinan法,一种是Sumly法,一种是30T法分别如下: 一.Mahuinan法: 用sed命令可以批量替换多个文件中的字符串. ...

  4. Java_类的热替换

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/#ibm-pcon Java ClassLoader 技术剖析 在本文中,我们 ...

  5. Linux中环境变量文件及配置

    Linux中环境变量文件及配置   一.环境变量文件介绍 转自:http://blog.csdn.net/cscmaker/article/details/7261921 Linux中环境变量包括系统 ...

  6. 【转】class卸载、热替换和Tomcat的热部署的分析

    这篇文章主要是分析Tomcat中关于热部署和JSP更新替换的原理,在此之前先介绍class的热替换和class的卸载的原理.一 class的热替换ClassLoader中重要的方法 loadClass ...

  7. class卸载、热替换和Tomcat的热部署的分析

    一 class的热替换 ClassLoader中重要的方法 loadClassClassLoader.loadClass(...) 是ClassLoader的入口点.当一个类没有指明用什么加载器加载的 ...

  8. Java 类的热替换---转载

    构建基于 Java 的在线升级系统 Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础 ...

  9. Linux中重命名文件

    linux下重命名文件有两种方式: 1.较简单的处理命令:mv mv 原文件名 新文件名 如:mv myFile newName 将MyFile重命名为newName. 2.linux提供了一个重命名 ...

随机推荐

  1. sqlserver学习2---java执行存储过程

    一.存储过程 1.新增操作存储过程 --------------1.新建 增加学生的存储过程---------------------------- set IDENTITY_INSERT stude ...

  2. IOS 即时通讯的框架 配置环境

    一.了解XMPP 协议(标准)XMPP 即时通讯协议SGIP 短信网关协议 这手机发短信 移动支付和网页支付 0x23232[0,1] 0x23232 0x23232 0x23232 只有协议,必须会 ...

  3. QT隐含共享类 QSharedData QSharedDataPointer

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/davidsu33/article/details/28857391 QT中非常多类都实现了隐含共享比 ...

  4. Uva 11491 暴力贪心

    题意:给一个n长度的整数,删掉 k 个数字,使得剩下的数字最大. 分析:还剩 n-k 个数字,就是在原序列里面,相对顺序不变的情况下,这个n-k个数字组成的数最大. 感觉没有什么特别好的方法策略,看了 ...

  5. 自定义Powershell提示符

    实现效果: 实现原理: Powershell将个人配置脚本文件的地址存放在$profile变量中, 通过修改该变量达到想要的目的. 实现过程: 1>创建一个新的配置脚本: 2>编辑脚本内容 ...

  6. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(一) 整理基础数据

    最近碰巧发现一款比较好的Web即时通讯前端组件,layim,百度关键字即可,我下面要做的就是基于这个前端组件配合后台完成即时聊天等功能.当然用到的技术就是ASP.NET SingalR框架.本人不会c ...

  7. caffe卷积层实现

    下图是jiayangqing在知乎上的回答,其实过程就是把image转换成矩阵,然后进行矩阵运算 卷积的实现在conv_layer层,conv_layer层继承了base_conv_layer层,ba ...

  8. sublime3插件安装方法

    sublime3插件安装方法:http://blog.csdn.net/u011627980/article/details/52171886

  9. Android学习笔记_27_多媒体之视频刻录

    一.配置文件: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android= ...

  10. Rman 管理 archivelog 的命令

    因为archivelog的相关信息是记录在controlfile中的,当物理删除后不会改变controlfile的设置.并且在查询相关的动态视图(例如v$archived_log)时,该部分日志仍然标 ...