在使用ps aux
命令检查进程,有一列STAT
字段,可以看到多种状态
D
不可中断睡眠状态(通常是IO或者是关键的系统进程,除非重启该进程不能被杀死)I
Idle状态的内核进程R
运行中或者可运行的(在运行队列中)状态S
可中断的睡眠状态 (等待一个事件完成后唤醒)T
停止状态,或者通过一个任务控制信号t
由于正在被跟踪而被debugger停止的进程W
分页中状态(在2.6.xx内核以后不再使用)X
死亡状态(以后不可见)Z
不工作("僵尸")进程,被终止的进程但是没有被父进程回收
对于BSD格式和其他使用的状态标记,附加字符含义:
<
高优先级(对其他用户不好)N
低优先级(对其他用户好)L
在内存中有锁住的页面(针对实时和定制IO)s
是一个会话领先者l
是一个多线程(使用CLONE_THREAD
,类似NPTL
pthreads那样)+
在前台进程组
在线上维护服务器的时候,经常会遇到由于磁盘故障导致进程进入
D
状态
使用
man ps
可以看到在PROCESS STATE CODES
段落下有上述进程状态解释
"僵尸进程"(Zombie Processes)产生原因:
当你运行一个程序时,它会产生一个父进程以及很多子进程。 所有这些子进程都会消耗内核分配给它们的内存和 CPU 资源。
这些子进程完成执行后会发送一个 Exit 信号然后死掉。这个 Exit 信号需要被父进程所读取。父进程需要随后调用 wait 命令来读取子进程的退出状态,并将子进程从进程表中移除。
若父进程正确第读取了子进程的 Exit 信号,则子进程会从进程表中删掉。
但若父进程未能读取到子进程的 Exit 信号,则这个子进程虽然完成执行处于死亡的状态,但也不会从进程表中删掉。
由于僵尸进程并不做任何事情, 不会使用任何资源也不会影响其它进程, 因此存在僵尸进程也没什么坏处。 不过由于进程表中的退出状态以及其它一些进程信息也是存储在内存中的,因此存在太多僵尸进程有时也会是一些问题。
- 找出僵尸进程
ps aux | grep Z
- 杀死僵尸进程
正常情况下我们可以用 SIGKILL 信号来杀死进程,但是僵尸进程已经死了, 你不能杀死已经死掉的东西。 因此你需要输入的命令应该是:
kill -s SIGCHLD pid
这里的 pid 替换成父进程的进程 id,这样父进程就会删除所有以及完成并死掉的子进程了。
不过许多程序写的不是那么好,无法删掉这些子僵尸(否则你一开始也见不到这些僵尸了)。 因此确保删除子僵尸的唯一方法就是杀掉它们的父进程。