Linux

為什麼必須在 pivot_root 之後執行 exec 來解除安裝舊的根文件系統?

  • November 4, 2021

簡介

pivot_root new_root put_old

問題

為什麼必須執行exec更改正在執行的執行檔才能解除安裝舊的根文件系統(put_old)?

假設put_old移動到不在新根文件系統 ( new_root) 內的目錄。那可以解除安裝嗎?

為什麼chroot執行後需要pivot_rootnew_root此時已經創建了新的根文件系統。

最後,如何pivot_root更改父程序的根目錄(例如bash),如果它是從 shell 派生的?更改不應該只影響pivot_root流程本身嗎?頁面中的“目前程序”是man指父程序還是pivot_root本身?

範例

mount /dev/hda1 /new-root
cd /new-root
pivot_root . old-root
exec chroot . sh <dev/console >dev/console 2>&1
umount /old-root

man pivot_root:

請注意, exec chroot更改正在執行的執行檔,如果以後應解除安裝舊的根目錄,則必須這樣做。

**問:**為什麼必須執行exec更改正在執行的執行檔才能解除安裝舊的根文件系統(put_old)?

因為文件系統在忙碌時無法解除安裝,並且如果正在執行的執行檔(例如bash)或其共享庫位於舊的根文件系統上,它們會使其保持忙碌狀態。


**問:**假設put_old移動到一個不在新根文件系統(new_root)內的目錄。那可以解除安裝嗎?

不允許put_oldnew_root之外。從系統呼叫的手冊頁

put_old必須位於或位於new_root之下


**Q:**為什麼chroot執行後需要pivot_rootnew_root此時已經創建了新的根文件系統。

不再需要它了。系統呼叫的原始手冊頁在 2019 年被大幅重寫[替代連結],更新的手冊頁[存檔連結][替代連結]解釋了行為和歷史不確定性:

pivot_root()如果它們指向舊的根目錄,則將同一掛載命名空間中的每個程序或執行緒的根目錄和目前工作目錄更改為new_root 。

$$ This behavior $$為了防止核心執行緒使舊的根掛載忙於它們的根目錄和目前工作目錄,這是必要的$$ … $$ …

歷史筆記

多年來,該手冊頁包含以下文本:

> > pivot_root()可能會也可能不會更改使用舊根目錄的任何程序或執行緒的目前根目錄和目前工作目錄。的呼叫者 > pivot_root()必須確保根目錄或目前工作目錄位於舊根目錄的程序在任何一種情況下都能正常執行。確保這一點的一種簡單方法是在呼叫之前將其根目錄和目前工作目錄更改 > 為new_rootpivot_root()。 > > >

這段文字是在系統呼叫實現甚至在核心中最終確定之前編寫的,可能是為了警告當時的使用者,在最終發布之前實現可能會發生變化。但是,描述中所述的行為自此系統呼叫首次實現以來一直保持一致,並且現在不會​​改變。


問:pivot_root最後,如果父程序的根目錄(例如bash)是從 shell 分叉的,如何更改它的根目錄?更改不應該只影響pivot_root流程本身嗎?頁面中的“目前程序”是man指父程序還是pivot_root本身?

這是因為pivot_root()在呼叫程序的掛載命名空間上進行操作,該命名空間與父程序共享。實用程序 ( pivot_root(8) ) 的手冊頁沒有明確說明這一點,但係統呼叫 ( pivot_root(2) ) 的更新手冊頁確實說明了這一點(強調添加):

pivot_root()更改呼叫程序的掛載命名空間中的根掛載。

$$ … $$ pivot_root()如果它們指向舊的根目錄,則將同一掛載命名空間中的每個程序或執行緒的根目錄和目前工作目錄更改為new_root 。

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