概要
cgroupのことについて調べたら、PID名前空間ってどこにあるんだろうって思って調べた自分メモメモ。なーんとなくしかわかっていないと思われるが、あたらずとも遠からずかなぁm(_ _)m。
pidとupid
プロセスIDは1234みたいにプロセスを一意に識別するただの番号に思えるが意外と単純でなく、カーネルでは多様なメンバで構成された構造体(pidとupid)の関連で表現されている。
↓
pidとupid
50 struct upid {
51 /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
52 int nr;
53 struct pid_namespace *ns;
54 struct hlist_node pid_chain;
55 };
56
57 struct pid
58 {
59 atomic_t count;
60 unsigned int level;
61 /* lists of tasks that use this pid */
62 struct hlist_head tasks[PIDTYPE_MAX];
63 struct rcu_head rcu;
64 struct upid numbers[1];
65 };
task_strcut->pidから辿れる。upid->nrがプロセス番号。pid->numbers[1]は可変配列みたいになっていて拡張可能でここがプロセスの階層を表わしている
ようだ(たぶn)。これのMAXはどこかでdefineされていて32個まで名前空間の階層は作成できるみたい。なのでプロセスの名前空間は32個しかもてない?プロセスはどこかの階層に属していてこの階層が親子の上下関係を表わしているでいいのかな??
ネストされた名前空間
プロセスは、所属する PID 名前空間の他のプロセスから見える。また、 root PID 名>前空間に向かう直径の先祖の各 PID 名前空間のプロセスからも見える。 この場合、「見える」とは、 あるプロセスが、 他のプロセスがプロセス ID を指定するシステムコール>を使う際に操作の対象にできることを意味する。 逆に、子供 PID 名前空間のプロセスか>ら親や先祖の名前空間のプロセスは見えない。
pidとupidの初期化はこのalloc_pid()でしていて、後述するtask_struct->nsproxy->pid_namespace(自分が所属している名前空間)からlevel(階層)を取得してそこから上に向かって各階層で自分のプロセス番号を設定している。すべての階層で自分のプロセス番号を取得して設定するが、結果として返すプロセス番号(nr)は自分が所属しているプロセス空間のプロセス番号(nr)になる。このプロセス番号はこの階層でしか一意でなく、よって他の階層だとプロセス番号はかぶることがある。
pid_namespace
24 struct pid_namespace {
25 struct kref kref;
26 struct pidmap pidmap[PIDMAP_ENTRIES];
27 struct rcu_head rcu;
28 int last_pid;
29 unsigned int nr_hashed;
30 struct task_struct *child_reaper;
31 struct kmem_cache *pid_cachep;
32 unsigned int level;
33 struct pid_namespace *parent;
34 #ifdef CONFIG_PROC_FS
35 struct vfsmount *proc_mnt;
36 struct dentry *proc_self;
37 struct dentry *proc_thread_self;
38 #endif
39 #ifdef CONFIG_BSD_PROCESS_ACCT
40 struct fs_pin *bacct;
41 #endif
42 struct user_namespace *user_ns;
43 struct work_struct proc_work;
44 kgid_t pid_gid;
45 int hide_pid;
46 int reboot; /* group exit code if this pidns was rebooted */
47 struct ns_common ns;
48 };
task_strcut->nsproxyから上記のpid_namespaceが辿れてプロセスを生成するときに初期化されるようだ。初期化するときにcloneでCLONE_NEWPID
が指定されていると、このnsproxyが新規のものにとって変わられるここで。
task_struct->nsproxy->pid_namespaceはこのプロセスが所属している名前空間を表わしている。pid_namespace->level
は階層。前述したpid->numbers[level]と対応している(たぶん)。
順番
まず、プロセスを生成するときにtask_struct->nsproxyを初期化して、自分の所属する名前空間を割り出して(level)、そこを起点として上にたどっていきtask_struct->pid->upidを初期化する。
参考
詳しくはこちらをご参照ください