Linux内核中kill_orphaned_pgrp函数是如何处理孤儿进程组的?

摘要:Linux 3.2 kill_orphaned_pgrp 函数 前言 之前研究进程的退出 do_exit, 其中一个重点就是 exit_notify, 遂对这个函数的用法产生了兴趣, 并且进行了一番研究. 1.想象一个场景 如果你玩过 sh
Linux 3.2 kill_orphaned_pgrp 函数 前言 之前研究进程的退出 do_exit, 其中一个重点就是 exit_notify, 遂对这个函数的用法产生了兴趣, 并且进行了一番研究. 1.想象一个场景 如果你玩过 shell, 你应该能理解下面的一个场景: sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % sleep 100 ^Z zsh: suspended sleep 100 sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % nc -l 8080 ^Z zsh: suspended nc -l 8080 sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % jobs [1] - suspended sleep 100 [2] + suspended nc -l 8080 sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % fg %1 [1] - continued sleep 100 ^Z zsh: suspended sleep 100 sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % bg %1 [1] - continued sleep 100 sudo-su-bash@Sudo-su-BashdeMacBook-Air ~ % exit 对, 按下 Ctrl+Z 可以让前台的进程暂时挂起, 然后使用 bg 可以让进程在后台运行. 但是随之而来的就有一个问题: 上面的代码, 我最后敲了 exit, shell挂了, 但是 sleep 和 nc 还挂在后台呢! 所以, 该怎么处置这两个怪胎? 接下来这个函数, 就是专门处置这个怪胎的. 2.函数的原型 这个函数的意图其实很简单, 看名字也可以看得出来, 就是检测是否为孤儿进程组, 并且唤醒/杀死孤儿进程组的所有 Stopped 状态的进程. 此函数的原型如下 static void kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent) { struct pid *pgrp = task_pgrp(tsk); struct task_struct *ignored_task = tsk; if (!parent) parent = tsk->real_parent; else ignored_task = NULL; if (task_pgrp(parent) != pgrp && task_session(parent) == task_session(tsk) && will_become_orphaned_pgrp(pgrp, ignored_task) && has_stopped_jobs(pgrp)) { __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); } } 初次看到, 肯定会感觉有点绕, 后面的代码勉强能看懂, 但是前面的代码是什么鬼? 为什么parent为null的时候, 会被自动赋值为父进程? ignored_task又是干什么的? 3. 下面一段代码的含义 3.1 孤儿进程组的判定 在开始之前, 我们先来看一个函数: //will_become_orphaned_pgrp static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignored_task) { //确定每个进程的父进程都在同一个进程组 struct task_struct *p; do_each_pid_task(pgrp, PIDTYPE_PGID, p) { if ((p == ignored_task) || //被忽略的进程 (p->exit_state && thread_group_empty(p)) || //这个进程只剩下一个线程了, 并且这个线程也不在运行 is_global_init(p->real_parent)) //父进程全局init continue; if (task_pgrp(p->
阅读全文