前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >僵尸进程的问题

僵尸进程的问题

作者头像
李海彬
发布2018-03-23 10:56:09
2.5K0
发布2018-03-23 10:56:09
举报
文章被收录于专栏:Golang语言社区

1、僵尸进程的产生

在AIX操作系统实施的进程结构中,每一个进程都有一个父进程。当一个进程结束时会通知它的父进程,从而该进程的父进程会收集该进程的状态信息。若父进程在一定的时间内无法收集到状态信息,则系统中就会残留一个僵尸进程。 因为僵尸进程是已经停止的,所以使用杀死进程的方法来杀僵尸进程是无效的。僵尸进程不使用CPU或硬盘等系统资源,而只使用极少量的内存用于存储退出状态和资源使用信息。

2、问题分析

某一个进程在结束时由它的父进程负责删除它。要找到某一个进程的父进程,执行ps -ef命令,输出中的PPID列给出了一个进程的父进程的进程号。 (1)PPID为1

如果一个僵尸进程的PPID为1,则该僵尸进程的父进程为init进程。

init进程是系统中所有进程的起源。

通常情况下,init进程通过将僵尸进程的PPID设为1来收回该进程。

如果一个僵尸进程的父进程号为1,则需要确认该僵尸进程是否已结束了若干分钟。(方法是等几分钟后再查看该僵尸进程是否还存在。)

一个系统中,特别是任务繁忙的系统中,父进程为init的僵尸进程存在1~2分钟是正常的。僵尸进程经常由复杂的shell脚本程序产生,这种情况通常是正常的,并不能说明有问题存在。

当init进程没有处理完/etc/inittab文件而在等其中的某一项命令结束(通常是一个/etc/rc脚本)时,可能会发生问题。

在这时候,init进程会忽略掉其它所有结束的子进程,而只等这个特定的子进程结束。

由一个挂起的/etc/inittab文件中的任务引起的问题的征兆是:父进程为init的僵尸进程无限制的增长。

在AIX4.3及以后的版本中,init进程的功能被增强,用以有效地处理僵尸进程。

如果/etc/inittab文件中含有类似下一行的项,则删除它: install_assist:2:wait:/usr/lib/lpd/pio/etc/pioinit >; /dev/null 2>;&1 该进程会引起僵尸进程。该项应在初始化安装结束后被自动删除。 (2)PPID不为1

如果父进程号不为1,则相应的父进程应负责收回结束的子进程。

未收回子进程的原因之一是shell管道。系统中的许多命令都不会产生子进程,这些进程也无法处理那些结束的子进程。这种情况在一个shell管道中有一个或多个短时进程及一个和多个长时间进程时更为明显。一个僵尸进程会在它的父进程运行期间一直存在。

任何一个程序在产生子进程时都应负责在子进程结束时收回它们。如果程序在编写中没有考虑到处理它们产生的子进程,则该程序存在问题。

(3)问题确认

如果确认一个进程是僵尸进程,并且该进程应该被它的父进程收回,则可能需要提供下面的信息给应用软件供应商用以分析问题产生的可能原因: 1)下面命令的输出: # ps -ef 2)下面命令的输出: # who -a 3)/etc/inittab 文件 4)下面命令的输出: SLOT=`expr <PID>; / 256`

(echo u $SLOT ; echo trace -k $SLOT) | crash >; <filename>;

3、处理方式

(在linux系统)忽略SIGCHLD信号,这常用于并发服务器的性能的一个技巧,因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源。如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。

signal(SIGCHLD, SIG_IGN);

...

pid = fork(); //生成一个子进程 if (pid < 0) // error check. handle_err();

if (pid == 0) exit (execl(....)); // child process. else if (wait(&ret) < 0) perror(/"wait/"); //parent process 在这里wait,都会得No Such process的错误,因为子进程终止后,内核会向父进程发送SIGCHLD信号,但是上面已将此信号设为忽略,实质上由init来接收此子进程的处理。

对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。

signal(SIGCHLD,SIG_IGN);

这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、僵尸进程的产生
  • 2、问题分析
  • 3、处理方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档