linux 2.6.23孤儿进程

来源:百度文库 编辑:神马文学网 时间:2024/04/27 21:38:26
forget_original_parent()定义:linux/kernel/exit.c
673/*
674 * When we die, we re-parent all our children.
675 * Try to give them to another thread in our thread
676 * group, and if no such member exists, give it to
677 * the child reaper process (ie "init") in our pid
678 * space.
679 */
680static void
681forget_original_parent(struct task_struct *father, struct list_head *to_release)
682{
683        struct task_struct *p, *reaper = father;
684        struct list_head *_p, *_n;
685
686        do {
687                reaper = next_thread(reaper);
688                if (reaper == father) {
689                        reaper = child_reaper(father);
690                        break;
691                }
692        } while (reaper->exit_state);
/**next_thread(reaper)找到当前线程组另一个线程。如果if判断条件不成立,找到新线程是孤儿进程新父亲
if条件成立,那么说明当前线程组没有其他线程,那么只有init为其父进程
694        /*
695         * There are only two places where our children can be:
696         *
697         * - in our child list
698         * - in our ptraced child list
699         *
700         * Search them and reparent children.
701         */
702        list_for_each_safe(_p, _n, &father->children) {
703                int ptrace;
704                p = list_entry(_p, struct task_struct, sibling);
706                ptrace = p->ptrace;
707
708                /* if father isn't the real parent, then ptrace must be enabled */
/**当前退出的线程不是其真正的父亲,那么必然是被跟踪的进程.否则在系统日志打印错误。
709                BUG_ON(father != p->real_parent && !ptrace);
/**如果当前退出进程是其真正的父亲,为退出进程的子进程设置新的父进程
711                if (father == p->real_parent) {
712                        /* reparent with a reaper, real father it's us */
713                        choose_new_parent(p, reaper);
714                        reparent_thread(p, father, 0);
715                }
/**如果当前EXIT_ZOMEBIE状态.父进程关系发生了改变,则应该向新的父进程发送信号
else {
716                        /* reparent ptraced task to its real parent */
/**本代码进程是跟踪即将退出的进程,被挂到退出进程的子链表上,后面详细解释.
_ptrace_unlink(p)解除与退出进程的父子关系(因为本进程即将退出),并挂到生父进程的子链表中。
717                        __ptrace_unlink (p);
718                        if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
719                            thread_group_empty(p))
720                                do_notify_parent(p, p->exit_signal);
721                }
/**如果子进程为僵尸状态,且退出时不给父进程信号就将其收集起来,到时候统一退出处理
723                /*
724                 * if the ptraced child is a zombie with exit_signal == -1
725                 * we must collect it before we exit, or it will remain
726                 * zombie forever since we prevented it from self-reap itself
727                 * while it was being traced by us, to be able to see it in wait4.
728                 */
729                if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
730                        list_add(&p->ptrace_list, to_release);
731        }
/**为当前退出进程,跟踪子进程设置新的父亲
732        list_for_each_safe(_p, _n, &father->ptrace_children) {
733                p = list_entry(_p, struct task_struct, ptrace_list);
734                choose_new_parent(p, reaper);
735                reparent_thread(p, father, 1);
736        }
737}
在694后续代码,主要遍历了子进程链表(father->children)和跟踪子进程链表(father->ptrace_children),给每个子进程设置
新的父进程。当一个进程被跟踪时,它被暂且设为调式进程的子进程。此时如果父进程退出,系统会为它们重新找到一个父进程。
对部分代码详细解释:
对BUG_ON定义:
23#ifndef HAVE_ARCH_BUG
24#define BUG() do { \
25        printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
26        panic("BUG!"); \
27} while (0)
28#endif
30#ifndef HAVE_ARCH_BUG_ON
31#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
作用:一些内核调用可以用来方便标记bug,提供断言并输出信息。最长用的两个是BUG()和BUG_ON()。当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。为什么这些声明会导致oops跟硬件的体系结构是相关的。大部分体系结构把BUG()和BUG_ON()定义成某种非法操作,这样自然会产生需要的oops。你可以把这些调用当作断言使用,想要断言某种情况不该发生:
if (bad_thing)
BUG();
或者使用更好的形式:
BUG_ON(bad_thing);
了解这个函数得区分几种子进程:
1    parent == real_parent 的子进程
这是本进程的子进程,并且没有被ptrace,处于本进程的children list上。
2   parent == father && parent != real_parent的子进程
被本进程ptrace的其它进程的子进程,处于本进程的children list上。
3   real_parent == father && parent != real_parent的子进程
本进程的子进程,但正在被其它进程ptrace,处于本进程的ptrace_children list上。
其中代码711~715和732~737对上述的(1)和(3)分别进程操作,设置其父进程为新找的父进程。
choose_new_parent()只是为子进程设置新的父亲,这个源代码很简单,看完我信心倍增。
注意:716~721是对第2种状态操作,和退出进程解除跟踪关系,将跟踪进程加入其生父进程。