我对僵尸进程有些疑问
提前致谢
答案 0 :(得分:12)
- 僵尸流程概念的好处是什么?
僵尸进程只是一个pid,一个退出状态,以及一些会计信息,这些信息会一直存在,直到父级使用wait
系列调用之一来获得其最终状态。在父母调用wait
之前,子进程ID必须保持标记为已使用,以便不能为其分配任何其他进程。如果要为另一个进程分配一个回收的pid,则很难区分它与之前具有相同pid的进程之间的区别。一旦父母调用wait
并返回最终退出状态,就可以假定没有人会再次在该pid处寻找孩子,因此现在可以重复使用pid。
(我认为在Linux上,如果父母将SIGCHLD作为SIG_IGN离开,内核将不会保留僵尸,但重新注册SIGCHLD的处置为SIG_IGN不具有相同的效果)
- 知道内核为僵尸进程保留(PID,终止状态,资源使用信息)“资源使用信息”是什么意思
其中一些信息是运行程序的:
time my_program
会报告。这些值通常在SIGCHLD的siginfo结构中报告(这不完全是对wait
的调用),但也可以通过调用waitid
形式的systme调用(在某些系统上)来获得。有关此结构的信息,请查看man sigaction
。
- 僵尸的PPID()= 1并且它仍然是僵尸,(init收获Zombies因为它默认等待())
一个僵尸的ppid = 1不应该长时间保持僵尸,因为 init 应该很快收获它。一个进程将在死亡后不久(通过exit
或通过一个无效的信号杀死它)保持僵尸,直到其父级调用wait
并获得它的最终状态。这意味着即使init除了一遍又一遍地调用init之外什么都不做,因此可能会有少量时间将进程显示为僵尸。如果进程在很长一段时间(秒)内显示为 init (0 = ppid)的子进程,则可能出现问题。
- 任何人都可以编写一些C代码来制作一个僵尸,它的父亲是Init?
目前尚不清楚,但我认为你想要:
pid_t f = fork();
if (f > 0) {
exit(0); // this is the parent dying, so the child will be an orphan
// and get adopted by init
} else if (f == 0) {
sleep(100); // This is the child doing something that takes enough time for
// its parent to commit suicide (exit(0)) and then for you to
// observe that it has now been adopted by init
exit(0); // And now it dyes as well, so init should reap its status, but
// it may be a zombie for a short amount of time first.
} else /* error condition would be handled here */
- 僵尸可以拒绝释放一些内存锁吗?
僵尸不能抓住任何东西。他们丢失了所有的内存页面,打开文件句柄等等。几乎所有操作系统都可以弄清楚如何释放应该被释放的东西。这不是一个错误,但请记住操作系统必须知道它应该被释放。在用户空间中创建资源非常容易,当程序死亡时,应该释放操作系统不知道应该被释放的资源。
答案 1 :(得分:3)
僵尸进程纯粹是一个pid和退出状态值。无法释放pid,因为资源(pid)“属于”父级。如果它被释放,另一个进程可能会被分配相同的pid,然后父进程可能最终向不相关的进程发送信号;即使父母首先等待确定孩子是否已经离开,也没有办法避免竞争条件。
答案 2 :(得分:2)
如果您有兴趣在正在运行的进程列表中查看僵尸进程,请使用以下命令:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
pid_t p = fork(); // creates child process and stores the returned PID
if (p != 0) // executed by parent process
{ sleep(1); /* the child process terminates while the parent process sleeps,
the child then becomes a zombie process because the returned status
of the terminated child process isn't checked via a wait() */
system("ps -eo pid,ppid,stat,cmd"); // prints a list of processes in your terminal
}
else // executed by child process
{
exit(0); // the child process terminates immediately
}
return 0;
}
您可以通过列表中的Z +识别僵尸进程:
注意:如果您使用的是Windows,则必须修改代码。
答案 3 :(得分:0)
僵尸进程是已经停止运行的进程,但是它们的进程表条目仍然存在,因为父进程尚未通过wait syscall检索到它。从技术上讲,每个终止过程在很短的时间内都是僵尸,但它们可以生存更长的时间。
当子进程完成后父进程未调用wait syscall时,将出现更长的僵尸进程。发生这种情况的一种情况是,当父进程的编写不佳,只是省略了wait调用,或者当父进程在子进程之前死亡而新的父进程没有对其调用wait时。当进程的父进程在子进程之前死亡时,操作系统会将子进程分配给“ init”进程或PID1。即,init进程“采用”子进程并成为其父进程。这意味着现在子进程退出时,新的父进程(init)必须调用wait来获取其退出代码,否则其进程表条目将永远保留并成为僵尸。