LoginSignup
7
6

More than 5 years have passed since last update.

PID名前空間

Posted at

概要

cgroupのことについて調べたら、PID名前空間ってどこにあるんだろうって思って調べた自分メモメモ。なーんとなくしかわかっていないと思われるが、あたらずとも遠からずかなぁm(_ _)m。

pidとupid

プロセスIDは1234みたいにプロセスを一意に識別するただの番号に思えるが意外と単純でなく、カーネルでは多様なメンバで構成された構造体(pidとupid)の関連で表現されている。

pidとupid

include/linux/pid.h
 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

Linux/include/linux/pid_namespace.h
 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を初期化する。

参考

詳しくはこちらをご参照ください

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6