Shared-Library

在依賴於它的程序正在執行時刪除共享庫是否安全?

  • August 20, 2021

在執行依賴於它的程序時,是否允許刪除(例如,使用rm命令)某些共享庫而沒有任何危險?我是這麼想的,因為如果程序正在執行,那麼庫中所有必要的數據都會被載入到記憶體中

但是我注意到,當我重寫庫(echo 123 > somelib.so)時,依賴它的程序由於Bus error

如果庫已經在記憶體中,為什麼程序會因為更改磁碟上的庫而崩潰?而如果庫不在記憶體中,那為什麼可以從磁碟中刪除,程序還會繼續執行呢?它從哪裡讀取庫中的數據?

我是這麼想的,因為如果程序正在執行,那麼庫中所有必要的數據都會被載入到記憶體中

可執行數據僅在需要時讀取,否則您將等待很長時間才能啟動諸如 Google Chrome 之類的重型應用程序(其二進製文件目前為179 134 080字節)。此外,Windows 中的 WinRAR 允許創建最大2^64 - 1大小的自解壓檔案。如果核心需要在啟動之前將所有程式碼載入到 RAM 中,您將永遠無法提取它們。

如果庫已經在記憶體中,為什麼程序會因為更改磁碟上的庫而崩潰?

它並不完全在記憶體中,它只映射到正在執行的程序。當核心決定實際執行庫中的程式碼時,它將被記憶體,但在那之前它只保留在您的磁碟驅動器上。

即使庫已經被執行,因此被讀取和記憶體,當核心記憶體不足時它仍然可以被記憶體出來。

它崩潰了,因為您實際上已經替換了文件並且核心試圖找到您要求執行的函式。一旦文件被覆蓋,這些功能就會變得垃圾,因此應用程序崩潰。

而如果庫不在記憶體中,那為什麼可以從磁碟中刪除,程序還會繼續執行呢?它從哪裡讀取庫中的數據?

Linux 核心中使用的 Unix 體系結構允許刪除打開的文件。由於此文件的句柄數大於零,因此在關閉最後一個句柄之前不會從技術上刪除該文件。

在依賴於它的程序正在執行時刪除共享庫是否安全?

是的,完美。覆蓋這樣的庫是不安全的。替換它再次是安全的,因為核心將使用舊的(已刪除的)庫。這就是您無需重新啟動系統即可替換幾乎所有庫的方法。只有當您替換它們時,您才必須重新啟動所有正在使用它們的應用程序。

最後,Linux 核心在幾年前進行了修補,以允許即時替換自身:https ://ostechnix.com/5-kernel-live-patching-tools-that-will-help-to-run-linux-servers -無需重新啟動/

通常,使用 刪除文件時,它們實際上並沒有被刪除rm,但只有在它們的所有打開文件句柄也都關閉之後。我很確定這也適用於文件映射到某個程序的記憶體時。之後rm,您將無法再次打開文件,但數據和映射仍然存在。

修改文件是另一回事,因為文件數據只有一個“版本”,所有讀取、寫入和共享映射訪問相同的數據。如果你在那裡寫垃圾,從文件中執行程式碼的程序也會得到垃圾。在 Linux 上,您不能對執行檔執行此操作,它會給出錯誤(“文本文件忙”),但對共享庫沒有這種保護。

(您可以嘗試:cp -a /bin/cat /tmp/cat; /tmp/cat &然後嘗試echo 123 >> /tmp/cat。然後fg返回cat,然後按 Ctrl-C 將其關閉。)

從技術上講,可以說rm根本沒有真正刪除文件,它只是刪除了文件名。一個文件可以有多個名稱,我們稱之為硬連結,但它基本上只是同一個文件的多個名稱。實際刪除通常是由刪除姓氏觸發的,但它有些獨立。

引用自:https://unix.stackexchange.com/questions/665479