ところで、pid_hash[][]からたどって、pid構造体を見つけても、タスク構造体のアドレスは容易に求めることができません。
なぜならば、pid構造体にはタスク構造体へのポインタはなく、単に埋め込まれているだけだからです。タスク構造体におけるpid構造体の位置を計算して、pid構造体のアドレスから計算すればよいということになります。
実際にやってみてください。
(gdb) p pid_hash
$1 = {0xc1403000, 0xc1405000, 0xc1407000, 0xc1409000}
(gdb) p pid_hash[0][0]
$2 = {first = 0xc0370384}
すぐにハッシュ値を求める必要が出てきました。
lxr.linux.noなどでpid_hashでカーネルソースを検索すると、
2.6.17では、
struct pid * fastcall find_pid(int nr)
{
struct hlist_node *elem;
struct pid *pid;
hlist_for_each_entry_rcu(pid, elem,
&pid_hash[pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
}
return NULL;
}
2.6.16では、
struct pid * fastcall find_pid(enum pid_type type, int nr)
{
struct hlist_node *elem;
struct pid *pid;
hlist_for_each_entry_rcu(pid, elem,
&pid_hash[type][pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
}
return NULL;
}
のようにpid番号からpid構造体を探す関数が見つかります。二つは、typeを引数に
取るかどうかが違いますが、遣っていることはほぼ一緒のようです。
2.6.17では、static struct hlist_head *pid_hash;と定義されているのに対して、
2.6.16では、static struct hlist_head *pid_hash[PIDTYPE_MAX];とtype別に
なっているようです。
さて、pid番号からタスク構造体を求める便利な関数はなんでしょうか。この見つかった
find_pidでさらに検索すると
2.6.16ではkernel/pid.cに
task_t *find_task_by_pid_type(int type, int nr)
{
struct pid *pid;
pid = find_pid(type, nr);
if (!pid)
return NULL;
return pid_task(&pid->pid_list, type);
}
EXPORT_SYMBOL(find_task_by_pid_type);
という関数があり、カーネル内部で自由に使えることが分かります。
やっと見つけたようです。


新しいコメントの投稿