在替换so文件时,如果在不停程序的情况下,直接用 cp new.so old.so 的方式替换程序使用的动态库文件会导致正在运行中的程序崩溃。解决的办法是采用“rm+cp” 或“mv+cp” 来替代直接“cp” 的操作方法。

linux系统的动态库有两种使用方法:运行时动态链接库,动态加载库并在程序控制之下使用。

1、在不停程序的情况下,直接用 cp 命令替换程序使用的 so 文件,导致程序崩溃:

这与 cp 命令的实现有关,cp 并不改变目标文件的 inode,cp 的目标文件会继承被覆盖文件的属性而非源文件。实际上它是这样实现的:

strace cp libnew.so libold.so 2>&1 |grep open.*lib.*.so

open("libnew.so", O_RDONLY|O_LARGEFILE) = 3

open("libold.so", O_WRONLY|O_TRUNC|O_LARGEFILE) = 4

在 cp 使用“O_WRONLY|O_TRUNC” 打开目标文件时,原 so 文件的镜像被意外的破坏了。这样动态链接器 ld.so 不能访问到 so 文件中的函数入口。从而导致 Segmentation fault,程序崩溃。

2、怎样在不停止程序的情况下替换so文件,并且保证程序不会崩溃?

答案是采用“rm+cp” 或“mv+cp” 来替代直接“cp” 的操作方法。

在用新的so文件 libnew.so 替换旧的so文件 libold.so 时,如果采用如下方法:

rm libold.so

cp libnew.so libold.so

采用这种方法,目标文件 libold.so 的 inode 其实已经改变了,原来的 libold.so 文件虽然不能用 ”ls”查看到,但其 inode 并没有被真正删除,直到内核释放对它的引用。同理,mv只是改变了文件名,其 inode 不变,新文件使用了新的 inode。这样动态链接器 ld.so 仍然使用原来文件的 inode 访问旧的 so 文件。因而程序依然能正常运行。

到这里,我们回想在上线操作中在替换可执行程序时,为什么直接使用“cp new old”这样的命令时,系统会禁止这样的操作,并且给出这样的提示“cp: cannot create regular file `old': Text file busy”。这时,我们采用的办法仍然是用“rm+cp”或者“mv+cp”来替代直接“cp”,这跟以上提到的so文件的替换有同样的道理。

但是,为什么系统会阻止 cp 覆盖可执行程序,而不阻止覆盖 so 文件呢?这是因为 Linux 有个 Demand Paging 机制,所谓“Demand Paging”,简单的说,就是系统为了节约物理内存开销,并不会程序运行时就将所有页(page)都加载到内存中,而只有在系统有访问需求时才将其加载。

“Demand Paging”要求正在运行中的程序镜像(注意,并非文件本身)不被意外修改,因此内核在启动程序后会锁定这个程序镜像的 inode。对于 so 文件,它是靠 ld.so 加载的,而ld.so毕竟也是用户态程序,没有权利去锁定inode,也不应与内核的文件系统底层实现耦合。

Linux替换动态库导致正在运行的程序崩溃的更多相关文章

  1. LINUX下动态库及版本号控制

    针对同一动态组件的不同版本链接和加载. 一.概念                  DLL HELL字面意思是DLL"灾难",是由于com组件(动态库)升级引起的程序不能运行的情况 ...

  2. LINUX总结第13篇:LINUX下动态库及版本号控制

    感觉讲得挺详细 注: ln 命令用法 ln –s 源文件 目标文件 (目标文件即为软链接文件) 可用ls -l查看软链接文件具体指向哪个文件 目录[-] 1. File libhello.c 2. F ...

  3. 谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH

    谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH  PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.ph ...

  4. Linux下动态库生成和使用

    Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中 ...

  5. 深入理解LINUX下动态库链接器/加载器ld-linux.so.2

    [ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...

  6. Linux生成动态库系统

    Linux生成动态库系统 一个.说明 Linux下动态库文件的扩展名为 ".so"(Shared Object). 依照约定,全部动态库文件名称的形式是libname.so(可能在 ...

  7. Linux下动态库和静态库的生成和使用

    1.准备头文件和源文件 hello.h #ifndef HELLO_H #define HELLO_H void hello(const char *name): #endif hello.c #in ...

  8. DELPHI开发LINUX的动态库

    DELPHI开发LINUX的动态库 WINDOWS的动态库是.dll,这个大家都知道. LINUX也有动态库,扩展名是.so,现在DELPHI也能开发LINUX的动态库哦. DELPHI对LINUX的 ...

  9. Linux进程线程学习笔记:运行新程序

    Linux进程线程学习笔记:运行新程序                                         周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...

随机推荐

  1. 023_supervisorctl管理服务注意事项

    一. (1)问题 我在线上使用supervisorctl管理服务时遇到程序文件更新了,但是下次supervisorctl执行的时候并没有更新, 原因是supervisor更新后必须重新读取加载文件才行 ...

  2. selenium——鼠标事件

    右键操作: 双击:

  3. typecho视频播放插件JWPlayer

    JWplayer for typecho是羽中大神开发并持续维护的一款插件,目前插件已经发布了8个版本,涵盖typecho0.8到1.0,插件基于原生的JWPlayer,可以说非常完美,详细使用方法在 ...

  4. JAVA 实现 简单的 HTTP服务器

    关于JAVA的HTTP服务器的简单实现,还望大家给出宝贵建议,谢谢. 1.首先来说下HTTP所有的状态碼,相信对于网页开发的博友们,肯定不陌生. 状态码 状态码英文名称 中文描述 100 Contin ...

  5. yum install 报错[Errno 14] curl#37 - Couldn't open file /mnt/repodata/repomd.xml

    最近在玩centos7,之前装系统没太注意yum这个东东,今天用别人装好的系统想用yum install 一个东西,结果报各种错,所以就是: 1.然后按照网上的一些修改,先是执行: yum cleam ...

  6. Python内置函数之classmetho staticmethod

    当对类的静态属性进行修改时(不需要借助于对象就行类静态属性的修改) class Goods: discount = 0.5 def __init__(self,name,price): self.na ...

  7. node20180927

    1. fs读文件.写文件 // 1 fs读文件 var fs = require('fs') fs.readFile('./20180926 demo/a.text', function (err, ...

  8. Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...

  9. 表单提交 fastadmin form

    1.引入form组件 require(['form'], function(Form){}); 2.生成form元素 3.绑定事件之验证(也可以绑定总表单事件Form.events.bindevent ...

  10. web服务-3、epoll高效率实现并发服务器

    知识点: 之前写的四种方法实现并发服务效率都还是低,早期的服务器采用的是select和poll方式,select这种方式的特点是轮询所有套接字去一个个看有没有事件发生,但是装套接字的列表长度是有限制的 ...