find_task_by_vpidを追ってみる
Rev.3を表示中。最新版はこちら。
サンプルでお世話になっているfind_task_by_vpidを追ってみました。これはプロセスIDからtask_structを取得するものです。task_structにはstruct pid_link pids[PIDTYPE_MAX]が紐づいていて、この配列の添え字にそって、PIDTYPE_PID | プロセスID |
PIDTYPE_TGID | スレッドグループID |
PIDTYPE_PGID | プロセスグループID |
PIDTYPE_SID | セッションID |
全プロセスIDをリストしているpid_hashから、まずpid構造体を取得します。pid構造体にはこのpidを使用しているtaskがリストされており、これからtask_strucを取得するというものでした。
流れは以下の通りです。(kernel/pid.c)
find_task_by_vpid find_task_by_pid_type_ns find_pid_ns pid_taskPIDTYPE_PIDでfind_task_by_pid_type_nsをコール
struct task_struct *find_task_by_vpid(pid_t vnr) { return find_task_by_pid_type_ns(PIDTYPE_PID, vnr, current->nsproxy->pid_ns); }find_pid_nsで該当pidを取得し、pid_taskでtask_structを取得。
struct task_struct *find_task_by_pid_type_ns(int type, int nr, struct pid_namespace *ns) { return pid_task(find_pid_ns(nr, ns), type); }pid_hashテーブルからプロセスIDとプロセスIDネームスペースの一致するpid を取得
struct pid *find_pid_ns(int nr, struct pid_namespace *ns) { struct hlist_node *elem; struct upid *pnr; hlist_for_each_entry_rcu(pnr, elem, &pid_hash[pid_hashfn(nr, ns)], pid_chain) if (pnr->nr == nr && pnr->ns == ns) return container_of(pnr, struct pid, numbers[ns->level]); return NULL; }pid が属するtask_structを取得
struct task_struct *pid_task(struct pid *pid, enum pid_type type) { struct task_struct *result = NULL; if (pid) { struct hlist_node *first; first = rcu_dereference(pid->tasks[type].first); if (first) result = hlist_entry(first, struct task_struct, pids[(type)].node); } return result; }プロセスIDおよびそのネームスペースからハッシュ値を計算
#define pid_hashfn(nr, ns) \ hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)