關於so文件cp覆蓋致使調用者core的研究

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

相關文章
相關標籤/搜索