a、该进程处于"Zombie"状态(使用ps命令返回defunct的进程)。此时进程已经释放所有资源,但还未得到其父进程的确认。"Zombie"进程要等到下次重启时才会消失,但它的存在不会影响系统性能。
b、 该进程处于"kernel mode"(核心态)且在等待不可获得的资源。处于核心态的进程忽略所有信号处理,因此对于这些一直处于核心态的进程只能通过重启系统实现。进程在AIX 中会处于两种状态,即用户态和核心态。只有处于用户态的进程才可以用“kill”命令将其终止
------------------------------------------------------------------------------------------------------------------------------------------------------------------
父进程在fork出子进程后,如果子进程死了,父进程没有给它收尸,就会产生僵尸进程。要杀死僵尸进程,只有两个办法:
1、改写父进程,在子进程死后要为它收尸。具体做法是接管SIGCHLD信号。子进程死后,会发送SIGCHLD信号给父进程,父进程收到此信号后,执行waitpid()函数为子进程收尸。
2、把父进程杀掉。父进程死后,它产生的所有僵尸进程也跟着消失。
以solaris为例:
// 在父进程中接管SIGCHLD信号
newact.sa_handler = Quit;
newact.sa_flags = 0;
newact.sa_handler = WaitChld;// WaitChld为SIGCHLD信号处理函数名
sigemptyset(&newact.sa_mask);
sigaction(SIGCHLD, &newact, NULL);
// WaitChld函数
void WaitChld(int sig)
{
char szRtnMsg[128];
int status, chld_term_sig;
pid_t pid;
pid = waitpid(0, &status, WNOHANG);
if (WIFEXITED(status) != 0) // 子进程正常退出
return;
strcpy(szRtnMsg, "子进程异常终止";
chld_term_sig = WTERMSIG(status);
switch (chld_term_sig) {
case SIGILL:
case SIGTRAP:
case SIGABRT:
//case SIGEMT:
case SIGFPE:
case SIGBUS:
case SIGSEGV:
//case SIGSYS:
case SIGXCPU:
strcat(szRtnMsg, "(CoreDumped)";
break;
case SIGQUIT:
case SIGKILL:
case SIGTERM:
strcat(szRtnMsg, "(Killed)";
break;
default:
break;
}
}
Reference:
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=717264&highlight= http://englishman2008.blog.163.com/blog/static/2801290720121016113225986/ https://blogs.oracle.com/haifeng/entry/unix_%E5%83%B5%E6%AD%BB_zombie_%E8%BF%9B%E7%A8%8B1 http://www.jb51.net/os/Solaris/1631_2.html preap (Solaris >= 9):除去僵尸进程 |