Linux替換動態庫導致正在執行的程式崩潰

2022-05-22 06:36:14 字數 1448 閱讀 2606

在替換so檔案時,如果在不停程式的情況下,直接用 cp new.so old.so 的方式替換程式使用的動態庫檔案會導致正在執行中的程式崩潰。解決的辦法是採用「rm+cp」 或「mv+cp」 來替代直接「cp」 的操作方法。

1、在不停程式的情況下,直接用 cp 命令替換程式使用的 so 檔案,導致程式崩潰:

這與 cp 命令的實現有關,cp 並不改變目標檔案的 inode,cp 的目標檔案會繼承被覆蓋檔案的屬性而非原始檔。實際上它是這樣實現的: 

strace cp libnew.so libold.so 2>&1 |grep open.*lib.*.so 

open("libnew.so", o_rdonly|o_largefile) = 3 

open("libold.so", o_wronly|o_trunc|o_largefile) = 4 

在 cp 使用「o_wronly|o_trunc」 開啟目標檔案時,原 so 檔案的映象被意外的破壞了。這樣動態鏈結器 ld.so 不能訪問到 so 檔案中的函式入口。從而導致 segmentation fault,程式崩潰。 

2、怎樣在不停止程式的情況下替換so檔案,並且保證程式不會崩潰? 

答案是採用「rm+cp」 或「mv+cp」 來替代直接「cp」 的操作方法。 

在用新的so檔案 libnew.so 替換舊的so檔案 libold.so 時,如果採用如下方法: 

rm libold.so 

cp libnew.so libold.so 

採用這種方法,目標檔案 libold.so 的 inode 其實已經改變了,原來的 libold.so 檔案雖然不能用 」ls」檢視到,但其 inode 並沒有被真正刪除,直到核心釋放對它的引用。同理,mv只是改變了檔名,其 inode 不變,新檔案使用了新的 inode。這樣動態鏈結器 ld.so 仍然使用原來檔案的 inode 訪問舊的 so 檔案。因而程式依然能正常執行。 

到這裡,我們回想在上線操作中在替換可執行程式時,為什麼直接使用「cp new old」這樣的命令時,系統會禁止這樣的操作,並且給出這樣的提示「cp: cannot create regular file `old': text file busy」。這時,我們採用的辦法仍然是用「rm+cp」或者「mv+cp」來替代直接「cp」,這跟以上提到的so檔案的替換有同樣的道理。 

但是,為什麼系統會阻止 cp 覆蓋可執行程式,而不阻止覆蓋 so 檔案呢?這是因為 linux 有個 demand paging 機制,所謂「demand paging」,簡單的說,就是系統為了節約物理記憶體開銷,並不會程式執行時就將所有頁(page)都載入到記憶體中,而只有在系統有訪問需求時才將其載入。 

「demand paging」要求正在執行中的程式映象(注意,並非檔案本身)不被意外修改,因此核心在啟動程式後會鎖定這個程式映象的 inode。對於 so 檔案,它是靠 ld.so 載入的,而ld.so畢竟也是使用者態程式,沒有權利去鎖定inode,也不應與核心的檔案系統底層實現耦合。

linux檢視正在執行的服務

linux檢視正在執行的服務 1.首先檢視 系統執行的程序 若需要檢視系統當前執行的所有程序,就需要用如下命令 ps auxw 其中引數a表示顯示系統中所有使用者的的程序 u表示輸出程序使用者所屬資訊 x表示也 顯示沒有控制台的程序 若顯示行太長而被截斷則可以使用f引數 www.2cto.com 2...

linux檢視正在執行的服務

1.首先檢視系統執行的程序 若需要檢視系統當前執行的所有程序,就需要用如下命令 ps auxw 其中引數a表示顯示系統中所有使用者的的程序 u表示輸出程序使用者所屬資訊 x表示也 顯示沒有控制台的程序 若顯示行太長而被截斷則可以使用f引數 2.檢視系統監聽的服務 netstat ln l表示顯示當前...

linux檢視正在執行的服務

linux檢視正在執行的服務 1.首先檢視系統執行的程序 若需要檢視系統當前執行的所有程序,就需要用如下命令 ps auxw 其中引數a表示顯示系統中所有使用者的的程序 u表示輸出程序使用者所屬資訊 x表示也 顯示沒有控制台的程序 若顯示行太長而被截斷則可以使用f引數 www.2cto.com 2....