在使用Linux做生产、开发过程中经常遇到有僵尸进程的出现,即使没遇到过也会对这个词有所耳闻,下面和大家一起简单聊下Linux中的这个僵尸进程。
僵尸,顾名思义是指已经死亡的但又以另一种形式存在的生命体。Linux中的进程也是一种生命体,生命周期体现在如下四个阶段:运行,等待,睡眠,终止。
运行:是cpu正在处理该进程的请求及运行代码;
等待:是指该进程处于可运行的状态但是由于某种原因(cpu冲高调度不过来,或是有更高优先级进程运行等)导致cpu并未处理该进程的运行,一旦得到调度即可运行;
睡眠:是指该进程需等待一个外部事件或是其他响应来触发,正常不会主动调度该进程到cpu上执行;
终止:就是进程收到另一个进程或用户的信号(SIGTERM、SIGKILL)而被杀死。
僵尸进程就是出现在终止进程的过程。
我们都知道Linux中对进程的管理主要是在内核态维护的一张进程表,里面记录了进程的状态信息等,进程正常终止时会释放占用资源,断开其他连接,并且父进程会发起wait for内核调用,通知内核态在进程表中清理该进程的信息。
当异常情况时即进程被终止,释放内存等资源,但父进程未能发起wait for系统调用而导致内核态中的进程表依然记录有该进程的信息,那么该进程状态是实际已经死亡,资源已经释放,不能再启动运行,但又以进程表中的表项信息存在着,所以称之为僵尸进程。
ps看到的Z状态进程,下面看到的STAT栏的是进程状态,如果出现Z状态就表示该进程已处于僵尸状态;如果是D状态进程处于睡眠状态,通常是在等待外设资源的响应。
僵尸进程处理目前我没看到有好的办法,ps或top都可以看到该进程的存在,但又没有实际运行的,没有特殊请求内核态也不会清理进程表中的该项,大部分的办法就是重启物理机了,可以放心的是这种僵尸进程不会对系统造成太大的影响,进程表中的记录只占用很少的空间。但是为了尽量避免僵尸进程的出现,我们在编写父进程代码是要时刻注意对子进程的管理,发起终止信号时要记得再进行wait for系统调用,养成良好的编码习惯。