Linux task_struct parent 和 real_parent 的区别

来源:互联网 发布:格罗玛什地狱咆哮知乎 编辑:程序博客网 时间:2024/05/22 06:06

注:以下信息总结自邮件列表 https://www.mail-archive.com/kernelnewbies@kernelnewbies.org/msg04745.html



Linux的 process descriptor 由 task_struct 结构表示

    struct task_struct {        // ...        /* real parent process */        struct task_struct __rcu *real_parent;         /* recipient of SIGCHLD, wait4() reports */        struct task_struct __rcu *parent;     }

这里,出现了两个parent,real_parentparentfork()一个子进程的同时,更新real_parent

至于信号SIGCHLD,谁ptrace了这个子进程,子进程结束后,SIGCHLD就发给对应的process,也就是这里的parent。换句话说,parent是在ptrace的时候设置的。





11/20/2015

在 Linux 2.6.11.12 do_fork()所调用的copy_process()中,若child->ptracePT_PTRACED标志被置位,将会调用__ptrace_link(child, current->parent)

__ptrace_link()child添加至真实parent的trace list后,修改child->parent,使其指向current->parent。从这里可以很直观地看出,task_struct.parent所指向的,是跟踪(trace)自己的进程,与之对应的,real_parent则是fork他的那个进程。

/* * This creates a new process as a copy of the old one, * but does not actually start it yet. * * It copies the registers, and all the appropriate * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */static task_t *copy_process(unsigned long clone_flags,                            unsigned long stack_start,                            struct pt_regs *regs,                            unsigned long stack_size,                            int __user *parent_tidptr,                            int __user *child_tidptr,                            int pid){    // ...    /* CLONE_PARENT re-uses the old parent */    if (clone_flags & (CLONE_PARENT|CLONE_THREAD))        p->real_parent = current->real_parent;    else        p->real_parent = current;    p->parent = p->real_parent;    // parent now is the same as real_parent    // ...    // if the PT_PTRACED bit is set    if (p->ptrace & PT_PTRACED)        __ptrace_link(p, current->parent);    // ...}/* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. * * Must be called with the tasklist lock write-held. */void __ptrace_link(task_t *child, task_t *new_parent){    if (!list_empty(&child->ptrace_list))        BUG();    if (child->parent == new_parent)        return;    // added to parent’s trace list    // note: child->parent == child->real_parent    list_add(&child->ptrace_list,             &child->parent->ptrace_children);    REMOVE_LINKS(child);    // child->parent now points to the debugger    child->parent = new_parent;    SET_LINKS(child);}





11/21/2015,Linux 2.6.11.12

进程退出时,将调用 exit_nofity(),这里所通知的,也是parent域所指向的进程(如果进程没有被跟踪,将有parent == real_parent)。

// file: exit.cvoid exit_notify(struct task_struct *tsk){    // ...    /* If something other than our normal parent is ptracing us, then     * send it a SIGCHLD instead of honoring exit_signal.  exit_signal     * only has special meaning to our real parent.     */    if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {        int signal = tsk->parent == tsk->real_parent                     ? tsk->exit_signal : SIGCHLD;        do_notify_parent(tsk, signal);    } else if (tsk->ptrace) {        do_notify_parent(tsk, SIGCHLD);    }    // ...}
0 0
原创粉丝点击