您的位置:首页 > 运维架构 > Linux

Linux task_struct parent 和 real_parent 的区别

2015-11-09 11:22 267 查看
注:以下信息总结自邮件列表 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_parent
parent
fork()
一个子进程的同时,更新
real_parent


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

11/20/2015

在 Linux 2.6.11.12
do_fork()
所调用的
copy_process()
中,若
child->ptrace
PT_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.c
void 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);
}

// ...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: