在依賴於它的程序正在執行時刪除共享庫是否安全?
在執行依賴於它的程序時,是否允許刪除(例如,使用
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
根本沒有真正刪除文件,它只是刪除了文件名。一個文件可以有多個名稱,我們稱之為硬連結,但它基本上只是同一個文件的多個名稱。實際刪除通常是由刪除姓氏觸發的,但它有些獨立。