スレッド/軽量プロセスとは
Rev.2を表示中。最新版はこちら。
スレッドとは軽量プロセスの事だと思っていました。この理解は結果的に正しいのですが、厳密にはそうでないようです。スレッドは軽量プロセスとして動作すると言ったほうが正しいようです。軽量プロセスとはその親プロセスとメモリー空間とかシグナル等のリソースを継承するもので、プロセス作成時CLONE_VM/CLONE_SIGHAND等を設定することで作成されます。スケジュール等での扱いにおいては通常のプロセスと変わりありません。
それではスレッドとはどのようなものでしょうか?プロセス作成と同じ流れで作成され、これもスケジュール等での扱いにおいては通常のプロセスと変わりありません。
プロセス/スレッド作成では、copy_process関数でまず親プロセスを複写するのですが、そのまえにCLON_FLAGに掛かるチェックを行います。
最初のチェックは、CLONE_THREADが指定されていると、CLONE_SIGHANDが指定されていなければなりません。これはスレッドはシグナルハンドラを共有することを意味します。2つ目のチェックはCLONE_SIGHANDが指定されていればCLONE_VMが指定されていなければなりません。結果的にスレッドではシグナルハンドラとメモリー空間を共有することになります。スレッドが軽量プロセスとなる所以です。
ここまでだとスレッドと軽量プロセスは同じものだと言うことですが、そもそもスレッドとは1つのプロセス内で各処理をマルチ処理で行うことを目的としたものです。従ってプロセス管理において、スレッドについてはそのような処理が施されます。
まず、struct task_structのpidにはスレッド独自のプロセスIDが割り当てられます。このIDはスレッド特別のIDが割り当てられるわけでありません。通常のプロセスのIDと同じです。しかしtgidには親のtgidが設定されます。すなわち全てのスレッドは同じtgidを持つことで、マルチスレッドプロセスにシグナルを送るとすべてのスレッドに送信することが可能となるわけです。
次にスレッドのreal_parentを、p->real_parent = current->real_parentとしていることです。プロセスではp->real_parent = currentとして、呼び出したプロセスが親になっていますが、スレッドでは作成したプロセスの親を設定していることです。すなわち親子関係は、スレッドを作成したプロセスとは親子関係でなく、兄弟関係のような扱いになるようです。またこの処理によりスレッドからスレッドを作成した場合も、親は同じになるということです。
スレッドを作成した最初のプロセスは、p->group_leader = current->group_leaderでプロセスグループとなり、しかも、p->group_leader->thread_group(p->group_leaderはcurrent->group_leader)で、呼び出しプロセスのthread_groupをヘッドとしてリスト管理されるということです。
static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *child_tidptr, struct pid *pid, int trace) { : if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) return ERR_PTR(-EINVAL); if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) return ERR_PTR(-EINVAL); : p->pid = pid_nr(pid); p->tgid = p->pid; if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; : if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { p->real_parent = current->real_parent; p->parent_exec_id = current->parent_exec_id; } else { p->real_parent = current; p->parent_exec_id = current->self_exec_id; } : if (clone_flags & CLONE_THREAD) { atomic_inc(¤t->signal->count); atomic_inc(¤t->signal->live); p->group_leader = current->group_leader; list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); : }プロセス作成において、軽量プロセスと言うものを作成する設定はありません。CLONE_FLAGにおいて、どのリソースを共有するかで結果的にそのプロセスを軽量プロセスと呼ぶだけのようです。