[转载] linux 程序运行过程中替换文件
今天被朋友问及“Linux下可以替换运行中的程序么?”,以前依稀记得Linux下是可以的(而Windows就不让),于是随口答道“OK”。结果朋友发来一个执行结果:(test正在运行中)
# cp test2 test cp: cannot create regular file `test': Text file busy
看起来是程序被占用,无法覆盖。于是自己又再做了几个实验:
(1)先rm删除正在运行的test,然后cp test2 test就没有错误了。
(2)先mv改名正在运行的test,然后cp test2 test也没有问题。
查了查资料并动手分析了一下,找到了比较满意的解释。cp并不改变目标文件的inode,事实上它的实现是这样的:
# strace cp test2 test 2>&1 | grep open.*test open("test2", O_RDONLY|O_LARGEFILE) = 3 open("test", O_WRONLY|O_TRUNC|O_LARGEFILE) = 4
我原以为cp的实现是“rm + open(O_CREAT)”,不过现在想想上面的实现方式才是最可靠的(保证了时序安全和目标文件的属性)。这也可以解释为什么cp的目标文件会继承被覆盖文件的属性而非源文件。
Linux由于Demand Paging机制的关系,必须确保正在运行中的程序镜像(注意,并非文件本身)不被意外修改,因此内核在启动程序后会锁定这个程序镜像的inode。这就是为什么cp在用“O_WRONLY|O_TRUNC”模式open目标文件时会失败。而先rm再cp的话,新文件的inode其实已经改变了,原 inode并没有被真正删除,直到内核释放对它的引用。同理,mv只是改变了文件名,其inode不变,新文件使用了新的inode。
问题到这里已经水落石出,不过刨根究底的个性驱使我再做了以下一组实验,没想到结果完全出乎我意料之外!
写了一个简单的测试程序:
#include <stdio.h> int main(int argc, char * argv[]) { foo(); // An export function by libtest.so. sleep(1000); return 0; }
foo()是另一个测试动态库libtest.so的导出接口,只打印一行提示就返回。接下来我把上面对执行文件的测试用例对动态库又做了一遍:
(1)cp libtest2.so libtest.so可以直接覆盖已加载的动态库。
(2)先rm删除已加载的libtest.so,然后cp libtest2.so libtest.so成功。
(3)先mv改名已加载的libtest.so,然后cp libtest2.so libtest.so成功。
除了第一个用例外,结果相同。这样看来,动态库被加载时难道ld并没有锁定inode?不过想想也可以宽恕,毕竟ld也是用户态程序,没有权利去锁定inode,也不应与内核的文件系统底层实现耦合。
到这里都还算在情理之中,看起来Linux也都处理的很好。不过还剩下一个问题:动态库被以cp的方式覆盖后难道不会和Demand Paging机制产生冲突?
在思考这个问题的过程中,我意识到前面这个测试程序的一个致命漏洞,稍作修改如下:
#include <stdio.h> int main(int argc, char * argv[]) { loop: foo(); // An export function by libtest.so. sleep(1); goto loop; return 0; }
这次,再执行上面的三个用例后发现,“cp libtest2.so libtest.so”虽然仍可直接覆盖已加载的动态库,但是测试程序马上出现了“Segmentation fault”。而后两个用例结果不变。由此可见,想要安全的替换已加载的动态库,还是用“笨拙”的“rm + cp”吧,看似捷径的“cp覆盖”会直接葬送掉你的程序……
看来,我再一次低估了Linux的健壮性,看似符合逻辑的流程也可能会带来灾难性的后果;“rm & cp”与“cp覆盖”背后所隐藏的底层差异却可以成为你的救星。Linux用得越久越是让人觉得这是一块充满了荆棘和陷阱的原始丛林,只有步步为营实踏前行才能走的更远。
注:以上实验基于SuSE Linux Enterprise Server 9 SP1(Linux 2.6.5 & glibc 2.3.3)。
[转载] linux 程序运行过程中替换文件的更多相关文章
- (转)在.NET程序运行过程中,什么是堆,什么是栈?什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?
转自:http://www.cnblogs.com/xiaoyao2011/archive/2011/09/09/2172427.html 在.NET程序运行过程中,什么是堆,什么是栈? 堆也就是托管 ...
- 程序运行过程中遇到“ORA-03114: not connected to ORACLE”的问题解决
c#,winform程序,数据批量入oracle库时用到DataAdaper的.FillSchema函数,如:da.FillSchema(dt2, SchemaType.Mapped); 程序运行一段 ...
- Java 程序运行过程中的内存分析
作为 java 程序员,都应该知道 Java 程序运行在 JVM(Java Virtual Machine,Java 虚拟机)上,可以把 JVM 理解成 Java 程序和操作系统之间的桥梁,JVM 实 ...
- 放在NSArray、NSDictionary等容器内的对象Item,Item中的property在程序运行过程中被无故释放
可能是被释放的property本身是OC对象而它的属性被误写成assign,例如: @interface MyItem : Object @property (nonatomic, assign) N ...
- robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)
1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...
- STM32在程序运行过程中关闭定时器重新打开后定时器不工作的问题
问题:数码管显示程序放在定时TIM2中断函数里面扫描,想要实现在关闭某一功能的时候数码管不显示. 刚开始的想法是开关关闭,关闭定时器时钟:开关打开,打开定时器时钟:(但实验证明再次打开开关时定时器2却 ...
- Java内存管理-程序运行过程(一)
勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 相信在做Java开发的伙伴一定知道 JVM(Java Virtual Machine( ...
- opencv检错:程序运行过程正常,当跳出函数时出现断言错误(Debug Assertion Failed)
转载http://blog.csdn.net/u012327581/article/details/51351780 1.问题描述 在VS2015下配置好Opencv后,程序在函数运行过程中正常,调试 ...
- java 程序运行过程 简介
这里的Java程序运行过程,是指我们编译好代码之后,在命令行开始执行java xxx命令,到java程序开始执行起来的这一过程,我们称其为运行时. 第一步,操作系统解析我们输入的java xxx命令, ...
随机推荐
- Oracle之虚拟索引
一.引言 DBA在日常维护管理数据库进行低性能SQL分析时,有时候需要通过创建索引对SQL进行优化,但有些时候我们创建的索引是否能用到?这个只能创建以后才能看出效果,但是在实际工作中,特别是对大表创建 ...
- drupal 自定义表单调用autocomplete主标签实现方法
代码如下: <php function module_name_form() { $form = array(); $form['city'] = array( '#title' => t ...
- 9、Http回顾/Servlet
1 Http回顾 Http协议: 1)http协议: 对浏览器客户端和服务器端之间数据传输的格式规范. 2)http请求:浏览器->服务器端 格式: 请求行(请求方式(GET/POST) 请求资 ...
- 如何查看Python的内置函数
经常调用的时候不知道python当前版本的内置函数是哪些,可以用下面的指令查看: C:\Users\Administrator>python Python 2.7.11 (v2.7.11:6d1 ...
- cookie与localstorage和sessionstorage的区别比较
保存位置: 三者均保存在浏览器端,且同源的. 与服务器的关系: cookie 数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递. sessionStorage ...
- 关于 android 中 postDelayed方法的讲解
代码如下: 这是一种可以创建多线程消息的函数 使用方法: 1,首先创建一个Handler对象 Handler handler=new Handler(); 2,然后创建一个Runnable对象 Run ...
- Python 主要模块和常用方法简览
******************** PY核心模块方法 ******************** 文件系统功能 os模块 目录: chdir() :改变工作目录 chroot ...
- android 入门 001 (界面布局)
学android 首先学会怎么布局界面,我开始是学.net的,因工作需要学习一下安卓,外行写的不好,请多多见谅指教 .这一篇文章然我们来学习一下四种布局吧! RelativeLayout(相对布局) ...
- 【leetcode❤python】326. Power of Three
#-*- coding: UTF-8 -*- class Solution(object): def isPowerOfThree(self, n): if n<=0: ...
- 从Unity学UE(一)之蓝图类的使用----制作一个可控灯光
转自:http://blog.csdn.net/u011707076/article/details/44171829 首先申明,本文章内容适合有Unity引擎基础的童鞋享用,如果不了解Unity引擎 ...