1、僵尸进程问题
父进程创建出子进程后,需要回收子进程,回收进程号。
C语言 fork() 出子进程后需要调用 wait
或 waitpid
方法。回收子进程。wait
会阻塞,waitpid
带 WNOHANG 参数的方法不会阻塞。
例如:使用 tini 作为init进程来管理我们的应用进程,tini 就会调用 waitpid 带 WNOHANG 参数的方法来清理僵尸进程。
在Java中很少去创建子进程来干活,一般都是创建线程,线程比进程轻量级。如下是创建子进程的代码。
|
|
同样的 Java 中的 Process 也有 wait 相关的方法。
2、限制容器内的进程数量
容器就是一些列的进程集合,容器内的进程是会映射到宿主机的,所以容器不能无限制的创建进程,否则最终会影响到宿主机。在宿主机的目录下(7ecd3aa7fdc15a1e183813b1899d5d939beafb11833ad6c8b0432536e5b9871c是容器id)的pids.max里面写入数字来限制容器内的进程数量。
/sys/fs/cgroup/pids/system.slice/docker-7ecd3aa7fdc15a1e183813b1899d5d939beafb11833ad6c8b0432536e5b9871c.scope
3、思考:init进程创建了b进程,b进程创建了c进程。如果c进程运行完成为了僵尸进程,b进程还在运行,init进程不断 waitpid ,c进程这个僵尸进程会不会被回收?
c进程不会被回收,waitpid 仅会等待直接子进程的状态变化。
为什么进程会进入僵尸进程而不是直接消失,是因为给父进程一次机会查看子进程的pid、终止状态(退出码、终止原因是信号终止还是正常退出等),还有子进程的资源使用情况。如果子进程直接消失那么父进程没有机会知道子进程的终止原因。一般情况下会根据子进程终止情况做出进一步处理。比如 Nginx Master 进程获知 worker 进程异常退出会重新拉起一个 worker 进程。