sys_cloneの第5,6引数について
do_fork関数の第5,6引数にint __user *parent_tidptr, int __user *child_tidptrというのが有ります。マニュアルによると、
ということのようですが・・・
この引数はユーザプロセスからsys_clone関数へ、そしてdo_fork関数へと渡される引数です。すなわちユーザメモリー空間のアドレスです。従ってここにプロセスIDを設定すれば、ユーザプロセスが子プロセスIDを参照することが可能になるというものです。
parent_tidptrは、do_fork関数内でCLONE_PARENT_SETTIDの時、copy_process処理後に子プロセスIDをput_user関数でにセットしています。
schedule_tail関数では、current->set_child_tidが設定されていたら、自分PIDをcurrent->set_child_tidにセットするようになっています。ここでのcurrentは、ret_from_fork関数からの呼び出しですから子プロセスとなります。
今ひとつ分かりませんが、まあとりあえずこんな感じということでした。
・追記
親はforkの返り値で子プロセスIDを取得できるわけだし、まして自プロセスのIDなんか・・・。この機能ってどのような目的で導入されたのでしょうか?
CLONE_PARENT_SETTID | 親プロセスと子プロセスのメモリ内の ptid が指す領域に子プロセスのスレッド ID を格納する。 |
CLONE_CHILD_SETTID | 子プロセスのメモリ内の ctid が指す場所に子プロセスのスレッド ID を格納する。 |
この引数はユーザプロセスからsys_clone関数へ、そしてdo_fork関数へと渡される引数です。すなわちユーザメモリー空間のアドレスです。従ってここにプロセスIDを設定すれば、ユーザプロセスが子プロセスIDを参照することが可能になるというものです。
parent_tidptrは、do_fork関数内でCLONE_PARENT_SETTIDの時、copy_process処理後に子プロセスIDをput_user関数でにセットしています。
long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) { : p = copy_process(clone_flags, stack_start, regs, stack_size, child_tidptr, NULL, trace); if (!IS_ERR(p)) { nr = task_pid_vnr(p); if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); : }child_tidptrはcopy_process関数内で、CLONE_CHILD_SETTIDの時p->set_child_tidにchild_tidptrを設定するだけで、この時点では、子プロセスIDを設定していません。どこで設定するかと言うと、子プロセスがスイッチングされる時にセットされています。
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) { : p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; : }子プロセスが起動するには、struct task_structのstruct thread_struct thread->ipに、ret_from_fork関数が設定されることで、スイッチングにおいてret_from_fork関数からスタートするようになっています。ret_from_fork関数ではまず、schedule_tail関数をコールしています。
schedule_tail関数では、current->set_child_tidが設定されていたら、自分PIDをcurrent->set_child_tidにセットするようになっています。ここでのcurrentは、ret_from_fork関数からの呼び出しですから子プロセスとなります。
asmlinkage void schedule_tail(struct task_struct *prev) __releases(rq->lock) { : if (current->set_child_tid) put_user(task_pid_vnr(current), current->set_child_tid); }で、確かにparent_tidptrには親プロセスメモリー空間, child_tidptrには子プロセスメモリー空間に、子プロセスIDが設定されるとは理解できるのですが、上記のマニュアルによると、CLONE_PARENT_SETTIDでは、親プロセスと子プロセスのメモリ内の設定されるということなのです。私の理解ではcopy_process関数内でCOWの設定を施している。と了解しています。もしCOWの設定がそれ以降で施されるのなら、なるほど。と言う事なのですが・・・
今ひとつ分かりませんが、まあとりあえずこんな感じということでした。
・追記
親はforkの返り値で子プロセスIDを取得できるわけだし、まして自プロセスのIDなんか・・・。この機能ってどのような目的で導入されたのでしょうか?