4.12 で nsfs の見た目がちょっと変わった
4.12 で nsfs に変更が加わってますね。
nsfs ってのは /proc/$PID/ns 以下の、そのプロセスがどの Namespace に所属しているのかを表している特殊なリンクがあるディレクトリです。
4.11 まではこんな感じ。
# ls -l /proc/self/ns total 0 lrwxrwxrwx 1 root root 0 Jul 4 17:14 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jul 4 17:14 ipc -> ipc:[4026531839] lrwxrwxrwx 1 root root 0 Jul 4 17:14 mnt -> mnt:[4026531840] lrwxrwxrwx 1 root root 0 Jul 4 17:14 net -> net:[4026531957] lrwxrwxrwx 1 root root 0 Jul 4 17:14 pid -> pid:[4026531836] lrwxrwxrwx 1 root root 0 Jul 4 17:14 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Jul 4 17:14 uts -> uts:[4026531838]
サポートしている Namespace それぞれの Namespace を表しています。
4.12 は
# ls -l /proc/self/ns total 0 lrwxrwxrwx 1 root root 0 Jul 4 17:00 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jul 4 17:00 ipc -> ipc:[4026531839] lrwxrwxrwx 1 root root 0 Jul 4 17:00 mnt -> mnt:[4026532397] lrwxrwxrwx 1 root root 0 Jul 4 17:00 net -> net:[4026531961] lrwxrwxrwx 1 root root 0 Jul 4 17:00 pid -> pid:[4026532399] lrwxrwxrwx 1 root root 0 Jul 4 17:00 pid_for_children -> pid:[4026532399] lrwxrwxrwx 1 root root 0 Jul 4 17:00 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Jul 4 17:00 uts -> uts:[4026531838]
こんな感じ。pid_for_children
というファイルが加わっています。CRIU 方面で必要だからということのようです (よく知りません)。kernel のコミットでいうと、
- ns: allow ns_entries to have custom symlink content
- pidns: expose task pid_ns_for_children to userspace
これは、PID Namespace だけちょっと特殊な部分があるからでしょうね。この辺りは Masami Ichikawa さんの、
の 28 ページ辺りをご覧になるのがよろしいかと。(nsfs についても 35 ページ辺りに言及があります)
つまり新しいプロセスを生成しない限りは、新しい PID Namespace に所属できません。unshare(2)
とか setns(2)
でも CLONE_NEWPID
は指定できますが、指定した新しい PID Namespace に所属するのはその子プロセスからです。
お気軽コンテナコマンド unshare
コマンドも --pid
だけ指定してもエラーになります。--fork
を同時に指定する必要があります。
ということは、プロセスの状態として、子供用に PID Namespace を持っていながら、自身は元の Namespace に所属しているという状態があるということですね。そういうプロセスの「子供用 PID Namespace を知る」ための機能ということでしょうか。
カーネルの Namespace を実現するための構造体、nsproxy
も
30 struct nsproxy { 31 atomic_t count; 32 struct uts_namespace *uts_ns; 33 struct ipc_namespace *ipc_ns; 34 struct mnt_namespace *mnt_ns; 35 struct pid_namespace *pid_ns_for_children; 36 struct net » *net_ns; 37 struct cgroup_namespace *cgroup_ns; 38 };
という風に pid_namespace *pid_ns_for_children
となってますね。これを表示しているのかな (たぶん)。
試してみました。
# unshare --mount --pid --mount-proc --fork # ls -l /proc/self/ns | grep pid lrwxrwxrwx 1 root root 0 Jul 4 17:27 pid -> pid:[4026532399] lrwxrwxrwx 1 root root 0 Jul 4 17:27 pid_for_children -> pid:[4026532399]
↑は新しい PID Namespace 内で調べてるのでまあこんな感じ。元の PID Namespace から見てみましょう。
# pgrep unshare 5354 # pstree -p 5354 unshare(5354)───bash(5355)
unshare
コマンド (pid: 5354) の子プロセスとして bash
が pid: 5355 で起動していますね。
# ls -l /proc/5354/ns | grep pid lrwxrwxrwx 1 root root 0 7月 4日 17:00 pid -> pid:[4026531836] lrwxrwxrwx 1 root root 0 7月 4日 17:00 pid_for_children -> pid:[4026532399] # ls -l /proc/5355/ns | grep pid lrwxrwxrwx 1 root root 0 7月 4日 17:00 pid -> pid:[4026532399] lrwxrwxrwx 1 root root 0 7月 4日 17:04 pid_for_children -> pid:[4026532399]
というわけで、unshare
コマンド自身の pid_for_children
は、子プロセスの bash
の pid
(PID Namespace) と一致していますね。でも unshare
コマンド自身の pid
(PID Namespace) はそれとは異なります。
というわけで、4.12 でちょっと nsfs に変わったのを調べてみました。(間違いの指摘歓迎!!)
nsproxy まわりについても同じく Ichikawa さんのブログが参考になります
- nsproxyとfork()周りのめも (φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ)