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种状态操作,和退出进程解除跟踪关系,将跟踪进程加入其生父进程。
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种状态操作,和退出进程解除跟踪关系,将跟踪进程加入其生父进程。
linux 2.6.23孤儿进程
Linux进程
Linux 进程管理
LINUX守护进程介绍
Linux 进程管理
LINUX守护进程介绍
linux 线程 进程经典文章
Linux进程的层次关系
linux 线程 进程经典文章
Linux进程间通信1
linux守护进程的编写
linux 开启 关闭 进程 tomcat
linux 2.6的shell脚本中如何kill掉 sleep进程
Linux 守护进程的编程方法
linux学习之进程篇1
Linux守护进程的编程方法 | 大学
Linux环境进程间通信(四)
Linux启动及控制服务进程
第三章 Linux下的进程管理
TASK_KILLABLE:Linux 中的新进程状态
100个最常见Linux守护进程
Linux 守护进程的编程方法--水碧桥
Linux 守护进程的编程方法--水碧桥
linux学习之进程篇1