Answers:
该程序实际上从未接收到SIGKILL信号,因为SIGKILL完全由操作系统/内核处理。
发送针对特定进程的SIGKILL后,内核的调度程序将立即停止为该进程提供更多的CPU时间来运行用户空间代码。如果进程在调度程序做出此决定时有任何线程在其他CPU /内核上执行用户空间代码,则这些线程也将停止。(在单核系统中,这过去要简单得多:如果系统中唯一的CPU核正在运行调度程序,那么从定义上讲它并不会同时运行进程!)
如果在SIGKILL时进程/线程正在执行内核代码(例如,系统调用或与内存映射文件相关联的I / O操作),则将变得有些棘手:只有某些系统调用可中断,因此内核在内部将进程标记为处于特殊的“濒死”状态,直到解决系统调用或I / O操作为止。解决这些问题的CPU时间将照常安排。可中断的系统调用或I / O操作将检查调用它们的进程是否在任何适当的停止点死亡,并且在这种情况下将提前退出。不间断的操作将完成,并且将在返回用户空间代码之前检查“垂死”状态。
一旦解决了任何进程中的内核例程,进程状态就会从“濒死”更改为“死亡”,并且内核开始清理它,类似于程序正常退出时的情况。清理完成后,将分配大于128的结果代码(以指示该进程已被信号杀死;有关混乱的详细信息,请参见此答案),然后该进程将转换为“僵尸”状态。终止进程的父进程将收到SIGCHLD信号通知。
结果,该过程本身将永远没有机会实际处理它已收到SIGKILL的信息。
当进程处于“僵尸”状态时,表示该进程已死,但其父进程尚未通过使用wait(2)
系统调用读取该死进程的退出代码来确认这一点。基本上,僵尸进程消耗的唯一资源是进程表中的一个插槽,该插槽中包含该进程的PID,退出代码以及该进程死亡时的其他“重要统计信息”。
如果父进程在其子进程之前死亡,那么孤立的子进程将被PID#1自动采用,PID#1承担继续调用的特殊职责,以使wait(2)
任何孤立的进程都不会像僵尸一样死守。
如果清理僵尸进程需要花费几分钟,则表明僵尸的父进程正在挣扎或无法正常工作。
关于在类似Unix的操作系统中出现僵尸问题的情况下,如何进行粗俗的描述:“您不能为僵尸本身做任何事情,因为它们已经死了。相反,请杀死邪恶的僵尸大师! ” (即麻烦的僵尸的父进程)
ps
:“ S”用于I / O等待内核可以取消以便传递信号,而“ D”等待它不能发送的信号。