sys_cloneの第5,6引数について


do_fork関数の第5,6引数にint __user *parent_tidptr, int __user *child_tidptrというのが有ります。マニュアルによると、
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なんか・・・。この機能ってどのような目的で導入されたのでしょうか?

最終更新 2011/05/16 04:46:59 - north
(2011/05/16 04:44:12 作成)


検索

アクセス数
3698084
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。