rootアクセス権を持つDebian jessieサーバーを使用してLinuxネームスペースを理解しようとしています。
次のCコードを考えてみましょう。
# /tmp/test.c
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static char child_stack[1048576];
static int my_child() {
system("/bin/bash");
}
int main() {
pid_t child_pid = clone(my_child, child_stack+1048576,
CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
waitpid(child_pid, NULL, 0);
return 0;
}
次に、単一端末の単一セッションで次のコマンドを実行します。
/tmp# id
uid=0(root) gid=0(root) groups=0(root),1093867019
/tmp# echo $$
1804
/tmp# ps -eaf | head
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 May08 ? 00:00:01 /sbin/init
root 2 0 0 May08 ? 00:00:00 [kthreadd]
root 3 2 0 May08 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 May08 ? 00:00:00 [kworker/0:0H]
root 7 2 0 May08 ? 00:00:11 [rcu_sched]
root 8 2 0 May08 ? 00:00:00 [rcu_bh]
root 9 2 0 May08 ? 00:00:00 [migration/0]
root 10 2 0 May08 ? 00:00:00 [watchdog/0]
root 11 2 0 May08 ? 00:00:00 [khelper]
/tmp# grep /proc /proc/$$/mountinfo
15 19 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:12 - proc proc rw
33 15 0:29 / /proc/sys/fs/binfmt_misc rw,relatime shared:20 - autofs systemd-1 rw,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct
/tmp# gcc test.c
/tmp# ./a.out
/tmp# echo $$
2
/tmp# echo $PPID
1
/tmp# ps -eaf | head
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 May08 ? 00:00:01 /sbin/init
root 2 0 0 May08 ? 00:00:00 [kthreadd]
root 3 2 0 May08 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 May08 ? 00:00:00 [kworker/0:0H]
root 7 2 0 May08 ? 00:00:11 [rcu_sched]
root 8 2 0 May08 ? 00:00:00 [rcu_bh]
root 9 2 0 May08 ? 00:00:00 [migration/0]
root 10 2 0 May08 ? 00:00:00 [watchdog/0]
root 11 2 0 May08 ? 00:00:00 [khelper]
tmp# grep /proc /proc/$$/mountinfo
15 19 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:12 - proc proc rw
33 15 0:29 / /proc/sys/fs/binfmt_misc rw,relatime shared:20 - autofs systemd-1 rw,fd=22,pgrp=0,timeout=300,minproto=5,maxproto=5,direct
/tmp# mount -t proc proc /proc
/tmp# grep /proc /proc/$$/mountinfo
92 70 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:12 - proc proc rw
93 92 0:29 / /proc/sys/fs/binfmt_misc rw,relatime shared:20 - autofs systemd-1 rw,fd=22,pgrp=0,timeout=300,minproto=5,maxproto=5,direct
97 92 0:34 / /proc rw,relatime shared:27 - proc proc rw
/tmp# ps -eaf
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:31 pts/0 00:00:00 ./a.out
root 2 1 0 07:31 pts/0 00:00:00 /bin/bash
root 14 2 0 07:31 pts/0 00:00:00 ps -eaf
/tmp# exit
exit
/tmp# echo $$
1804
/tmp# grep /proc /proc/$$/mountinfo
grep: /proc/1804/mountinfo: No such file or directory
/tmp# ps -eaf
Error, do this: mount -t proc proc /proc
/tmp# mount -t proc proc /proc
/tmp# grep /proc /proc/$$/mountinfo
15 19 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:12 - proc proc rw
33 15 0:29 / /proc/sys/fs/binfmt_misc rw,relatime shared:20 - autofs systemd-1 rw,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct
98 15 0:34 / /proc rw,relatime shared:27 - proc proc rw
69 98 0:3 / /proc rw,relatime shared:28 - proc proc rw
終了後に子プロセスが/proc
マウントされないのはなぜですか?子プロセスでマウントポイントを変更した場合、親プロセスのマウントポイントに影響を与えないでください。これは質問に対するEmmettの答えと矛盾するようです。https://stackoverflow.com/questions/22889241/linux-understanding-the-mount-namespace-clone-clone-newns-flag。
答え1
clone
このフラグを使用して子プロセスが作成されると、子CLONE_NEWNS
プロセスは独自のマウントネームスペースを取得します。子ネームスペースのマウント操作(mount
、umount
など)mount --bind
はそのネームスペース内でのみ有効ですが、親ネームスペースのマウント操作は新しいネームスペースの外部でのみ有効です。
共有インストールは例外です。マウントは次のとおりです。共有、この場合、ジョブは共有にマウントされたすべての名前空間に影響します。共有マウントの一般的な使用例は、サブネームスペース(chrootなど)でリムーバブルドライブを使用できるようにすることです。他の関係タイプ(プライベートマウント、バインドできないマウント)を参照してください。カーネル文書。
以下を確認して、マウントが共有されていることを確認できます。行に含まれている場合は、マウントが共有され、その数値は共有される名前空間のセットを識別する一意の値です。行にそのようなマークがない場合、インストールはプライベートです。/proc/PID/mountinfo
shared:NUMBER
あなたのシステムで/proc
共有されます。子ネームスペースにprocの新しいインスタンスをマウントすると、親ネームスペースにマウントされるため、新しいインスタンスも共有されるため、/proc
子ネームスペースと親ネームスペースの両方で表示できます。子ネームスペースを終了すると、2番目のインスタンスは/proc
まだアクティブな親ネームスペースと共有されるため、マウントされたままになります。
シナリオを複雑にする2つのことは、PID名前空間を作成し、/proc
実験対象と観察手段の両方として使用することです。インストールしていないとps
文句を言うと、/proc
実際に誤ったエラーメッセージが表示されます。間違った proc
インストール済み(aはproc
無効な名前空間を示す)とをls /proc
使用してこれを観察できますcat /proc/1/mountinfo
。一時ファイルシステムを試してみることをお勧めします。そうすれば、何が起こっているのかを理解するのは簡単です。
親# ./a.out 子供たち #echo$$ 2 子#ls / proc これは親のprocです。 /proc/PID は親 PID 名前空間にあります。 子供#ps 1 …内部に 子 # mount -t proc proc /proc 子マウントネームスペースの/ procが子PIDネームスペースに使用されるようになりました。 子供#ps 1 ...a。出力 子供#退場 父#
これまでは、プライベートなのか共有なのかは重要ではありませんでしたが、/proc
今は重要です。非公開の場合は、この時点で影響を受けたことがなく、PID名前空間を表示する/proc
親トピックを調べます。/proc
ただし/proc
、共有されている場合、mount
以前に実行したコマンドは両方の名前空間に影響を与えるため、次のようになります。
親番号ls / proc ACPIサウンドバディインフォ... 親番号ps 1 エラーが発生しました。次の操作を行います。 mount -t proc proc /proc 実際には/ procがマウントされていますが、これは以前に作成したPID名前空間のprocであり、現在実行中のプロセスはありません。 親 # grep -c ' /proc ' /proc/mounts 2 親#削除/proc 親名前空間/ procの子PID名前空間を隠した/ procをアンマウントしたため、「正常」/ procが再び表示されます。 親番号ps 1 …内部に