Answers:
要回答这个问题,您必须了解如何将信号发送到进程以及内核中进程如何存在。
每个进程都表示为task_struct
内核内部(定义在sched.h
头文件中,从此处开始)。该结构保存有关该过程的信息;例如pid。重要信息在行1566中,其中存储了相关的信号。仅当信号发送到过程时才设置。
死进程或僵尸进程仍然具有task_struct
。该结构保持不变,直到wait()
接收SIGCHLD
到父进程(自然进程或通过采用进程)后调用该进程以获取其子进程。发送信号后,将signal_struct
设置。在这种情况下,信号是否可捕获都无关紧要。
每次运行过程时都会评估信号。或者准确的说,之前的过程会运行。然后该过程处于TASK_RUNNING
状态。内核运行该schedule()
例程,该例程根据其调度算法确定下一个正在运行的进程。假设此过程是下一个正在运行的过程,则将signal_struct
评估的值,无论是否有等待信号要处理。如果手动定义了信号处理程序(通过signal()
或sigaction()
),则执行注册的功能,否则,将执行信号的默认操作。默认操作取决于发送的信号。
例如,SIGSTOP
信号的默认处理程序会将当前进程的状态更改为TASK_STOPPED
,然后运行schedule()
以选择要运行的新进程。请注意,SIGSTOP
它不是可捕获的(例如SIGKILL
),因此无法注册手动信号处理程序。如果出现无法捕获的信号,将始终执行默认操作。
对你的问题:
调度程序永远不会确定已失效或无效的进程是否TASK_RUNNING
再次处于该状态。因此,内核将永远不会为相应的信号(无论是哪个信号)运行信号处理程序(默认或已定义)。因此,exit_signal
将不再设置。该信号通过设置“交付”给过程signal_struct
中task_struct
的过程中,但什么都没发生,因为这个过程永远不会再运行。没有要运行的代码,流程的其余全部就是流程结构。
但是,如果父进程通过来获得其子进程wait()
,则它收到的退出代码是该进程“最初”死亡时的退出代码。是否有信号等待处理并不重要。
僵尸进程基本上已经死了。唯一的是,没有人知道它已经死了,因此它继续占用进程表中的一个条目以及一个控制块(Linux内核为活动中的每个线程维护的结构)。回收其他资源,例如文件上的强制性锁,共享内存段,信号灯等。
您无法向他们发出信号,因为没有人可以对此信号采取行动。即使致命的信号,如KILL,也没有用,因为该进程已经终止了其执行。您可以尝试:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid = fork();
if (pid == -1)
exit(-1);
if (pid > 0) {
//parent
printf("[parent]: I'm the parent, the pid of my child is %i\n"
"I'll start waiting for it in 10 seconds.\n", pid);
sleep(10);
int status;
wait(&status);
if (WIFSIGNALED(status)) {
printf("[parent]: My child has died from a signal: %i\n", WTERMSIG(status));
} else if (WIFEXITED(status)) {
printf("[parent]: My child has died from natural death\n");
} else {
printf("[parent]: I don't know what happened to my child\n");
}
} else {
//child
printf("[child]: I'm dying soon, try to kill me.\n");
sleep(5);
printf("[child]: Dying now!\n");
}
return 0;
}
在这里,我启动了一个进程,该进程在等待其子进程之前分叉并进入睡眠状态。这个孩子什么也没做,只是睡了一点。您可以在孩子睡觉时或刚退出时杀死孩子,以查看区别:
$ make zombie
cc zombie.c -o zombie
$ ./zombie
[parent]: I'm the parent, the pid of my child is 16693
I'll start waiting for it in 10 seconds.
[child]: I'm dying soon, try to kill me.
# Here, I did "kill -15 16693" in another console
[parent]: My child has died from a signal: 15
$ ./zombie
[parent]: I'm the parent, the pid of my child is 16717
I'll start waiting for it in 10 seconds.
[child]: I'm dying soon, try to kill me.
[child]: Dying now!
# Here, I did "kill -15 16717" in another console
[parent]: My child has died from natural death
ruby -e "loop while fork { exit! }"
... imgur.com/SoRXErm
kill
本身返回0还是1?