【问题标题】:How can a process kill itself?进程如何杀死自己?
【发布时间】:2011-06-05 16:36:25
【问题描述】:
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>

int main(){

    pid_t pid = fork();

    if(pid==0){
            system("watch ls");
    }
    else{
            sleep(5);
            killpg(getpid(),SIGTERM);  //to kill the complete process tree.
    }
    return 0;
}

终端:

anirudh@anirudh-Aspire-5920:~/Desktop/testing$ gcc test.c
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ ./a.out
Terminated

前 5 秒显示“watch ls”的输出,然后它终止,因为我发送了一个 SIGTERM。

问题:进程如何杀死自己?我已经完成了 kill(getpid(),SIGTERM);

我的假设: 所以在 kill() 调用过程中,进程切换到内核模式。 kill 调用将 SIGTERM 发送到进程并将其复制到进程的进程表中。当进程返回用户模式时,它会在其表中看到信号并自行终止(如何?我真的不知道) (我认为我的假设中某处出错了(可能是一个错误)......所以请赐教)

此代码实际上是我用来测试项目的其他模块的存根。 它为我完成了这项工作,我对此感到满意,但在我的脑海中存在一个问题,一个过程实际上是如何杀死自己的。我想知道分步假设。

提前致谢

阿尼鲁德·托默

【问题讨论】:

  • 为什么进程要杀死自己?如果它决定终止,它不只是调用exit()吗?
  • 你如何杀死没有生命的东西???
  • 原因是在上述情况下,如果你调用 exit() 而不是 kill 那么只有父进程被杀死。子进程成为孤儿,init 成为它的新父进程,它仍在继续运行。
  • 我希望终止整个进程树。如果我使用 killpg(pid,SIGTERM) 它对我不起作用,它只会杀死孩子,并且“system()”函数的进程会继续运行。我尝试做 killpg(getpid(),SIGTERM) 并且它为我完成了这项工作。但同样的问题是这怎么可能?
  • 也许你应该编辑你的问题来询问如何杀死整个进程树,因为这似乎是你真正想要的。

标签: linux process kill signal-handling sigterm


【解决方案1】:
kill(getpid(), SIGKILL);  // itself I think

我在 fork 使用 case 0: 之后对其进行了测试,它从单独的父进程中定期退出。

不知道这算不算标准的认证方式....

(我可以从我的 psensor 工具中看到 CPU 使用率返回 34%,就像普通程序代码一样 一个计数器停止了)。

【讨论】:

    【解决方案2】:

    这在 Perl 中非常简单:

       { 
            local $SIG{TERM} = "IGNORE";
            kill TERM => -$$;
       }
    

    转换为 C 留给读者作为练习。

    【讨论】:

    • Perl 是从哪里来的??不过感谢分享信息。我不知道 perl 所以可能当我开始使用它时,我会看到这个东西,
    【解决方案3】:

    所以在 kill() 调用过程中,进程切换到内核模式。 kill 调用将 SIGTERM 发送到进程并将其复制到进程的进程表中。当进程返回用户模式时,它会在其表中看到信号并自行终止(如何?我真的不知道)

    在 Linux 中,当从内核模式返回到用户空间模式时,内核会检查是否有任何待处理的信号可以传递。如果有一些,它会在返回用户空间模式之前传递信号。它还可以在其他时间传递信号,例如,如果一个进程在 select() 上被阻塞然后被杀死,或者当一个线程访问一个未映射的内存位置时。

    【讨论】:

      【解决方案4】:

      您的进程死亡是因为您使用了killpg(),它向进程组而不是进程发送信号。

      当你fork() 时,子进程继承自父亲,除此之外,还有进程组。来自man fork

         *  The child's parent process ID is the same as the parent's process ID.
      

      所以你把父母和孩子一起杀了。

      如果你做一个简单的kill(getpid(), SIGTERM),那么父亲会杀了孩子(即watching ls)然后会和平退出。

      【讨论】:

      • 不,这是不正确的。在我上面的代码中,只需将killpg 替换为kill,您将在 5 秒后看到父进程死亡,子进程被 init 进程继承。那个时候做 ps -a 。我做错的另一件事是killpg(getpid(),SIGTERM);,但由于父进程的 pgid 和 pid 相同,所以它在这里工作。子进程也有相同的 pgid。它应该是killpg(getpgid(getpid()),SIGTERM);,当 BASH 派生并执行一个子进程时,它会更改它 pgid 并使其等于它的 pid,这样即使子进程执行 killpg bash 仍然是安全的。
      【解决方案5】:

      我认为当它在其进程表中看到 SIGTERM 信号时,它首先杀死其子进程(完整的树,因为我调用了 killpg() )然后它调用 exit()。

      我仍在寻找这个问题的更好答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-12
        • 1970-01-01
        • 2017-08-05
        • 1970-01-01
        • 2019-03-28
        • 1970-01-01
        • 2018-04-26
        • 1970-01-01
        相关资源
        最近更新 更多