linux进程管理之wait系统调用
发布时间:2016-02-07 21:19:44 所属栏目:Linux 来源:网络整理
导读:六: wait4 ()系统调用 在父进程中,用wait4()可以获得子进程的退出状态,并且防止在父进程退出前,子进程退出造成僵死 状态。这是我们这节分析的最后一个小节了
|
对僵尸进程的操作是由wait_task_zombie()完成的。代如如下:
static int wait_task_zombie(struct task_struct *p, int noreap,
struct siginfo __user *infop,
int __user *stat_addr, struct rusage __user *ru)
{
unsigned long state;
int retval;
int status;
//WNOWAIT被设置.不需要释放子进程的资源,只要取相关信息即可
if (unlikely(noreap)) {
pid_t pid = p->pid;
uid_t uid = p->uid;
int exit_code = p->exit_code;
int why, status;
//子进程不为EXIT_ZOMBIE .异常退出
if (unlikely(p->exit_state != EXIT_ZOMBIE))
return 0;
//没有退出信号具没有被跟踪.退出
if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
return 0;
//增加引用计数
get_task_struct(p);
read_unlock(&tasklist_lock);
if ((exit_code & 0x7f) == 0) {
why = CLD_EXITED;
status = exit_code >> 8;
} else {
why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
status = exit_code & 0x7f;
}
//取相关信息
return wait_noreap_copyout(p, pid, uid, why,
status, infop, ru);
}
/*
* Try to move the task's state to DEAD
* only one thread is allowed to do this:
*/
//将子进程状态设为EXIT_DEAD状态
state = xchg(&p->exit_state, EXIT_DEAD);
//如果子进程不为EXIT_ZOMBIE状态,异常退出
if (state != EXIT_ZOMBIE) {
BUG_ON(state != EXIT_DEAD);
return 0;
}
//没有退出信号,且没有被跟踪
if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
return 0;
}
//子进程的real_parent等于当前父进程.说明子进程并没有被跟踪出去
if (likely(p->real_parent == p->parent) && likely(p->signal)) {
struct signal_struct *psig;
struct signal_struct *sig;
//更新父进程的一些统计信息
spin_lock_irq(&p->parent->sighand->siglock);
psig = p->parent->signal;
sig = p->signal;
psig->cutime =
cputime_add(psig->cutime,
cputime_add(p->utime,
cputime_add(sig->utime,
sig->cutime)));
psig->cstime =
cputime_add(psig->cstime,
cputime_add(p->stime,
cputime_add(sig->stime,
sig->cstime)));
psig->cmin_flt +=
p->min_flt + sig->min_flt + sig->cmin_flt;
psig->cmaj_flt +=
p->maj_flt + sig->maj_flt + sig->cmaj_flt;
psig->cnvcsw +=
p->nvcsw + sig->nvcsw + sig->cnvcsw;
psig->cnivcsw +=
p->nivcsw + sig->nivcsw + sig->cnivcsw;
psig->cinblock +=
task_io_get_inblock(p) +
sig->inblock + sig->cinblock;
psig->coublock +=
task_io_get_oublock(p) +
sig->oublock + sig->coublock;
spin_unlock_irq(&p->parent->sighand->siglock);
}
/*
* Now we are sure this task is interesting, and no other
* thread can reap it because we set its state to EXIT_DEAD.
*/
//取得相关的退出信息
read_unlock(&tasklist_lock);
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
status = (p->signal->flags & SIGNAL_GROUP_EXIT)
? p->signal->group_exit_code : p->exit_code;
if (!retval && stat_addr)
retval = put_user(status, stat_addr);
if (!retval && infop)
retval = put_user(SIGCHLD, &infop->si_signo);
if (!retval && infop)
retval = put_user(0, &infop->si_errno);
if (!retval && infop) {
int why;
if ((status & 0x7f) == 0) {
why = CLD_EXITED;
status >>= 8;
} else {
why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
status &= 0x7f;
}
retval = put_user((short)why, &infop->si_code);
if (!retval)
retval = put_user(status, &infop->si_status);
}
if (!retval && infop)
retval = put_user(p->pid, &infop->si_pid);
if (!retval && infop)
retval = put_user(p->uid, &infop->si_uid);
if (retval) {
// TODO: is this safe?
p->exit_state = EXIT_ZOMBIE;
return retval;
}
retval = p->pid;
//当前进程不是生父进程.则说明进程是被跟踪出去了
// TODO:子进程exit退出的时候,只会向其当前父进程发送信号的哦^_^
if (p->real_parent != p->parent) {
write_lock_irq(&tasklist_lock);
/* Double-check with lock held. */
if (p->real_parent != p->parent) {
//将进程从跟踪链表中脱落,并设置父进程为生父进程
__ptrace_unlink(p);
// TODO: is this safe?
//重新设置为EXIT_ZOMBI状态
p->exit_state = EXIT_ZOMBIE;
/*
* If this is not a detached task, notify the parent.
* If it's still not detached after that, don't release
* it now.
*/
//如果允许发送信息,则给生父进程发送相关信号
if (p->exit_signal != -1) {
do_notify_parent(p, p->exit_signal);
if (p->exit_signal != -1)
p = NULL;
}
}
write_unlock_irq(&tasklist_lock);
}
//释放子进程的剩余资源
if (p != NULL)
release_task(p);
BUG_ON(!retval);
return retval;
}
至此,我们看到了继子进程退出之后的完整处理。在此,值得注意的是。子进程在退出的时候会给父 进程发送相应的信号(例如SIG_CHILD),默认的信号处理函数也会进行相应的处理。 (编辑:应用网_镇江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐

