先說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