天天看點

Linux下動态連結庫so檔案覆寫導緻coredump

1.為什麼cp的方式更新運作中程序的so,程式會coredump

2.采用什麼方式更新已經加載了的so,就可以避免coredump

我們的公共元件絕大部分都支援so形式的自定義插件,比如s++,qzhttp,ttc。在不停程序更新so的時候往往會産生coredump,并且肯定core得莫名其妙,core得讓人心碎。

先看一下用cp的方式更新so的時候發生了什麼事情

strace cp new.so old.so #strace是人間利器

[img]http://leeon.me/upload/2011-11/20111130111113_44195.gif[/img]

發現老的so被trunc了,這個過程發生的具體的事情是:

1.應用程式通過dlopen打開so的時候,kernel通過mmap把so加載到程序位址空間,對應于vma裡的幾個page.

2.在這個過程中loader會把so裡面引用的外部符号例如malloc printf等解析成真正的虛存位址。

3.當so被cp覆寫時,确切地說是被trunc時,kernel會把so檔案在虛拟内的頁purge 掉。

4.當運作到so裡面的代碼時,因為實體記憶體中不再有實際的資料(僅存在于虛存空間内),會産生一次缺頁中斷。

5.Kernel從so檔案中copy一份到記憶體中去,a)但是這時的全局符号表并沒有經過解析,當調用到時就産生segment fault , b)如果需要的檔案偏移大于新的so的位址範圍,就會産生bus error.

是以,如果用相同的so去覆寫

A) 如果so 裡面依賴了外部符号,coredump

B) 如果so裡面沒有依賴外部符号,運氣不錯,不會coredump

所有問題的産生都是因為so被trunc了一把,是以如果不用turnc的方式就避免這個問題。Ok,該我們的install 上場了。

strace install new.so old.so

[img]http://leeon.me/upload/2011-11/20111130111151_36601.png[/img]

install 的方式跟cp不同,先unlink再creat,當unlink的時候,已經map的虛拟空間vma中的inode結點沒有變,隻有inode結點的引用計數為0是,kernel才把它幹掉。

也就是新的so和舊的so用的不是同一個inode結點,是以不會互相影響。這時隻有得啟程式才會使用到新的so。是以采用這種方式的話就可以避免先stop程序,更新so,再重新開機程序這樣比較耗時的操作。