先说cp好mv/rm的区别:node
cp from to,则被覆盖文件 to的inode依旧不变(属性也不变),内容变为from的;安全
mv from to,则to的inode变为from的,相应的,to的属性也成了from的;rm相似;函数
问题,假如程序 main.out依赖的so文件libtest.so被cp掉,会发生什么?spa
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的目标文件会继承被覆盖文件的属性而非源文件。.net
Linux因为Demand Paging机制的关系,必须确保正在运行中的程序镜像(注意,并不是文件自己)不被意外修改,所以内核在启动程序后会绑定 内存页 到这个so的inode,而一旦此inode文件被open函数O_TRUNC掉,则kernel会把so文件对应在虚存的页清空,这样当运行到so里面的代码时,由于物理内存中再也不有实际的数据(仅存在于虚存空间内),会产生一次缺页中断。Kernel从so文件中copy一份到内存中去,a)可是这时的全局符号表并无通过解析,当调用到时就产生segment fault , b)若是须要的文件偏移大于新的so的地址范围,就会产生bus error。blog
备注:若是用相同的so去cp覆盖
A) 若是so 里面依赖了外部符号(如标准库),coredump
B) 若是so里面没有依赖外部符号,运气不错,不会coredump继承
没必要说,先rm再cp的话,新文件的inode其实已经改变了,原inode并无被真正删除,直到内核释放对它的引用(引用旧SO的进程退出,而新进程固然呈现的就是新so的效果了,新进程和core无关啦)。同理,mv只是改变了文件名,其inode不变,新文件使用了新的inode。进程
参考: 内存
[1]http://www.piao2010.com/%E4%B8%BA%E4%BD%95cp%E8%A6%86%E7%9B%96%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%8A%A8%E6%80%81%E5%BA%93so%E4%BC%9A%E5%AF%BC%E8%87%B4coredumptest
[2]http://blog.csdn.net/wei_yongtao/article/details/40145891