linux僵尸进程&&进程进入不可中断休眠状态


1.平台Hi3536发现某些进程使用(kill -9)杀不掉

ps查看指令为      ps -o pid,ppid,stat,comm

stat :
     D       不可中断         Uninterruptible sleep (usually IO)
                                         R       正在运行,或在队列中的进程
                                         S       处于休眠状态
                                         T       停止或被追踪
                                         Z       僵尸进程
                                         W       进入内存交换(从内核2.6开始无效)
                                         X       死掉的进程
                                         <       高优先级
                                         N       低优先级
                                         L       有些页被锁进内存
                                         s       包含子进程
                                         +       位于后台的进程组;
                                         l       多线程,克隆线程

其中程序进入僵尸进程和不可中断的休眠状态进程都是依靠kill -9杀不掉的。


2.僵尸进程产生原因,危害,规避办法及补救办法:

产生原因:

在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵尸进程。

僵尸进程危害:

在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放. 但这样就导致了问题,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

僵尸进程的规避方案

⒈父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起。
⒉ 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后, 父进程会收到该信号,可以在handler中调用wait回收。
⒊ 如果 父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD,SIG_IGN) 通知 内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号。
⒋ 还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一 个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收 还要自己做。

补救办法

杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。

不可中断的休眠状态进程产生原因,解决办法

产生原因:
这种状态出现的情形主要是等待关键资源或者等待系统调用结束的时候会出现。进程处于此状态时,不能响应异步信号,不能被kill -9等信号结束,只能等待wake_up()。不可中断睡眠,只能被如硬件中断、正在等待的资源被释放等唤醒,对其他的进程传递不响应。
不可中断睡眠状态与可中断睡眠状态类似,但是它有一个例外,那就是把信号传递到这种睡眠 状态的进程不能改变它的状态,也就是说它不响应信号的唤醒。不可中断睡眠状态一般较少用到,但在一些特定情况下这种状态还是很有用的,比如说:进程必须等 待,不能被中断,直到某个特定的事件发生。



题外:

一个进程对kill -9不响应的有两种情况

  1. 未接受到信号或者没有得到分配的时间来完成自己退出所需要的步骤,比如CPU100%时,多等一些时间应该会自动中止

  2. 进程处于IO等待中这时候屏蔽了信号接收自然不会对KILL作出响应,除非IO的请求得到响应,要判断这种情况你可以看 ps aux|grep vi看看进程状态, 如果是 D 那就是了,这个情乱会麻烦一点因为它需要请求的IO得到满足或者被拒绝,而系统没有给与明确的答复他就一直干等着,根据你的描述你需要看这个打开的文件的情况,如果是nfs,那么建议在添加挂载选项为 bg,hard,intr避免这个问题的重现,如果是本地文件你需要察看硬盘或者存储阵列卡是否有问题但是要杀死这个进程却需要重启来解决


另外:该进程处于"kernel mode"(核心态)且在等待不可获得的资源。处于核心态的进程忽略所有信号处理,因此对于这些一直处于核心态的进程只能通过重启系统实现。进程在unix/linux中会处于两种状态,即用户态和核心态。只有处于用户态的进程才可以用“kill”命令将其终止。








  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值