2017-06-21 99 views
3

我與Linux的命名空間實驗。特別是pid命名空間。取消共享--pid /斌/慶典 - 叉無法分配內存

我想我考出來的東西在bash,但碰到這樣的問題:

unshare -p /bin/bash 
bash: fork: Cannot allocate memory 

從那裏用ls了核心轉儲。退出是唯一可能的事情。

爲什麼這樣做?

回答

3

的錯誤是由新的命名空間的PID 1的進程退出引起的。

慶典開始運行後,bash將叉幾個新的子流程做出頭。如果你沒有-f運行取消共享,bash將有PID爲當前的「停止共享」的過程一樣。目前的「不共享」的過程調用取消共享系統調用,創建一個新的PID命名空間,但目前的「不共享」的過程是不是在新的PID命名空間。它是linux內核的期望行爲:進程A創建一個新的命名空間,進程A本身不會被放入新的命名空間,只有進程A的子進程將被放入新的命名空間。所以,當你運行:

 
unshare -p /bin/bash 

的取消共享過程將Exec的/斌/ bash中,和/斌/慶典叉幾個子流程,慶典的第一子進程將成爲新的命名空間的PID 1和該子流程將在完成其作業後退出。因此,新名稱空間的PID 1退出。

的PID 1進程具有特殊的功能:它應該成爲所有孤兒進程的父進程。如果根名稱空間中的PID 1進程退出,內核將會出現混亂。如果子名稱空間中的PID 1進程退出,則linux內核將調用disable_pid_allocation函數,該函數將清除該名稱空間中的PIDNS_HASH_ADDING標誌。當linux內核創建一個新進程時,內核將調用alloc_pid函數在名稱空間中分配PID,並且如果未設置PIDNS_HASH_ADDING標誌,則alloc_pid函數將返回-ENOMEM錯誤。這就是爲什麼你得到「無法分配內存」錯誤。

您可以通過使用解決此問題的「-f」選項:

 
unshare -fp /bin/bash 

如果運行不共享與「-f」選項,取消共享將一個新的進程就創建新的PID命名空間之後。並在新進程中運行/ bin/bash。新進程將是新pid命名空間的pid 1。然後bash還會分叉幾個子流程來完成一些工作。由於bash本身就是新pid命名空間的pid 1,所以它的子進程可以毫無問題地退出。

+0

要回復這個非常有用的答案和一些手冊頁參考:['man 2 unshare'](http://man7.org/linux/man-pages/man2/unshare.2.html)關於CLONE_NEWPID ':_不共享PID名稱空間,以便調用進程爲其子項創建一個新的PID名稱空間,該名稱空間不與任何先前存在的進程共享。調用過程不會移入新的名稱空間。 **由調用進程創建的第一個子進程將具有進程標識1 **,並將在新名稱空間中承擔init(1)的角色._ – nh2

1

這並不能解釋爲什麼出現這種情況,但顯示瞭如何正確地推出了殼牌在一個新的PID命名空間:

使用-f標誌叉掉從unshare外殼:

unshare -fp /bin/bash 

您還需要通過--mount-proc選項以確保shell將在新創建的命名空間中獲得PID 1:

unshare -fp --mount-proc /bin/bash 

現在運行ps

# ps 
    PID TTY   TIME CMD 
1 pts/1 00:00:00 bash 
11 pts/1 00:00:00 ps