為什麼必須在 pivot_root
之後執行 exec
來解除安裝舊的根文件系統?
簡介:
pivot_root new_root put_old
問題:
為什麼必須執行
exec
更改正在執行的執行檔才能解除安裝舊的根文件系統(put_old
)?假設
put_old
移動到不在新根文件系統 (new_root
) 內的目錄。那可以解除安裝嗎?為什麼
chroot
執行後需要pivot_root
?new_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_old在new_root之外。從系統呼叫的手冊頁:
put_old必須位於或位於new_root之下
**Q:**為什麼
chroot
執行後需要pivot_root
?new_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 。