私はLinuxネームスペースを試しています。特にpid名前空間。unshare --pid/bin/bash-forkはメモリを割り当てることができません
私はbashので何かアウトをテストしたが、この問題に遭遇しようと思いました。そこから
unshare -p /bin/bash
bash: fork: Cannot allocate memory
実行lsがコアダンプを与えました。可能なのは出口だけです。
これはなぜですか?
私はLinuxネームスペースを試しています。特にpid名前空間。unshare --pid/bin/bash-forkはメモリを割り当てることができません
私はbashので何かアウトをテストしたが、この問題に遭遇しようと思いました。そこから
unshare -p /bin/bash
bash: fork: Cannot allocate memory
実行lsがコアダンプを与えました。可能なのは出口だけです。
これはなぜですか?
エラーが新しい名前空間にPID 1プロセスが終了によって引き起こされます。
bashの実行が開始されると、bashはいくつかの新しいサブプロセスをforkして何かを実行します。 -fなしでunshareを実行すると、bashは現在の "unshare"プロセスと同じpidを持ちます。現在の "unshare"プロセスはunshare systemcallを呼び出し、新しいpid名前空間を作成しますが、現在の "unshare"プロセスは新しいpid名前空間にありません。これはLinuxカーネルの望ましい動作です。プロセスAは新しい名前空間を作成し、プロセスA自体は新しい名前空間に入れられず、プロセスAのサブプロセスだけが新しい名前空間に入れられます。あなたが実行したときので:いくつかのサブプロセスの共有を解除プロセスは、/ binに/ bashのをexecします
unshare -p /bin/bash
を、および/ binに/ bashのフォークは、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」を使用することで、この問題を解決することができます:あなたは「-f」オプションと共有解除を実行した場合、それは新しいPID名前空間を作成した後、共有解除は、新しいプロセスをforkします
unshare -fp /bin/bash
。そして、新しいプロセスで/ bin/bashを実行してください。新しいプロセスは、新しいpid名前空間のpid 1になります。次に、bashはいくつかのサブプロセスをforkしていくつかのジョブを実行します。 bash自体は新しいpid名前空間のpid 1であるため、そのサブプロセスは問題なく終了できます。
この問題が発生したが、正しく新しいPID名前空間でシェルを起動する方法を示していますこれはなぜを説明していません:
がunshare
からシェルをオフフォークする-f
フラグを使用します。
unshare -fp /bin/bash
--mount-proc
オプションも渡して、新しく作成された名前空間でシェルがPID 1を取得するようにする必要があります。
今ps
を実行します。
# ps
PID TTY TIME CMD
1 pts/1 00:00:00 bash
11 pts/1 00:00:00 ps
この非常に参考になる回答をいくつかのmanページの参考文献に戻すには、['man 2 unshare'](http://man7.org/linux/man-pages/man2/unshare.2.html)では' CLONE_NEWPID ':_UnshareはPID名前空間を共有するので、呼び出しプロセスには、既存のプロセスと共有されていない子プロセスのための新しいPID名前空間があります。呼び出し元のプロセスは新しい名前空間に移動されません。 **呼び出したプロセスによって作成された最初の子は、プロセスID 1 **を持ち、新しい名前空間でinit(1)の役割を担います。 – nh2