僵尸进程

僵尸进程会导致系统资源的泄漏,其主要涉及父子进程、孤儿进程等概念,详细内容如下:

子进程

每个子进程都是由其父进程调用fork()\vfork()\clone()等系统调用而生成的。例如,在 shell 中执行一个命令时,shell 进程就会调用 fork() 产生一个子进程,然后子进程调用 exec() 执行命令程序,进程结束后返回控制至父进程 shell 进程。
子进程退出的时候会向其父进程发送一个SIGCHLD信号。

僵尸进程

对于终止的进程,内核会释放其使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息。这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息。
僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程。

孤儿进程

如果一个进程终止,而该进程有子进程处于僵尸状态,子进程被称为孤儿进程,孤儿进程由 init 进程收养,它的 PPID 变为 1。

如何避免僵尸进程

  • 1、通过signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心,由内核回收。
  • 2、父进程调用wait/waitpid等待子进程结束,(wait会阻塞父进程直至子进程退出、waitpid可以通过WNOHANG参数使父进程不阻塞立即返回)
  • 3、注册signal处理函数,在处理函数调用wait/waitpid等待子进程退出。这里需要关注的一点是:Linux的信号机制是不排队的,假如在某一时间段多个子进程退出后都会发出SIGCHLD信号,但父进程来不及一个一个地响应,所以最后父进程实际上只执行了一次信号处理函数
  • 4、通过两次调用fork。
父进程A fork子进程1, 然后父进程waitpid等待子进程1退出
子进程1 fork孙进程1, 然后子进程1退出。

这里子进程1退出后会被父进程A回收。而对于孙子进程其父进程已经退出,故孙进程->孤儿进程,程由init进程接管,孙进程结束后,init会等待回收。

reference

linux下的僵尸进程处理SIGCHLD信号
Linux 基础 —— Linux 进程的管理与监控

你可能感兴趣的:(僵尸进程)