linux-interface-zombie-process
June 25, 2019
僵尸进程
在父进程执行wait之前, 其子进程就已经终止,这将会发生什么?此处的重点在于: 即使子进程已经结束,系统仍然需要允许父进程在其之后的某一时间去执行wait,来获取子进程的结束状态。
所以内核将子进程转为僵尸进程来完成情况的处理,无法通过信号来杀死僵尸进程,这保证了父进程总是能够使用wait方法。这时候会释放子进程把持的发部分资源。以便供其他进程重新使用,其所保留的仅有内核进程表中的一条记录(其中包含了进程ID、终止状态、资源使用状况等信息)。
两种情况:
- 当父进程执行完wait后,不再需要子进程剩余的最后信息,内核会将删除僵尸进程,
- 父进程没有执行wait,退出之后,init进程将接管子进程,并自动调用wait,从而删除僵尸进程。
所以,一个长周期的父进程,应该总是执行wait方法,以防止僵尸进程的大量产生,导致无用的信息填满内核进程表。
杀死僵尸进程的唯一方法是:杀死其父进程,从而使init进程接管僵尸进程,并移除僵尸进程。
具体避免长寿僵尸进程的几种方法:
- 父进程调用wait方法来接受子进程。一种为阻塞式,一种为非阻塞,轮询方式
- 使用SIGCHLD信号处理程序: 可以对SIGCHLD信号安装处理程序,来对子进程的终止做出反应,在其中wait子进程,因为信号的中断处理方式,导致处理函数需要避免几个问题: 1)防止信号丢弃,导致少调用wait方法 2)需要提前安装信号处理器 3)信号传递特征导致的信号通病。
- 显式的忽略终止的子进程: 显式的将SIGCHLD 处置为SIG_IGN, 系统在子进程终止后立即删除,没有转换为僵尸进程的状态过程,也不需要wait调用。不过较老的UNIX实现并不能够正确处理这样的情况,导致不具有可移植性。
class A
@@name = “A”
@name = “a”
def self.a
p @@name
p @name
end
def a
p @@name
self.class.a
end
end
class B < A
def self.b
p @@name
self.a
end
def b
p @@name
self.class.b
p “-“ * 20
self.class.b
end
end
@name 类变量, 为 ruby 的类的实例变量, 不为继承体系所继承,
@@name 类变量, 为继承体系所继承