什么是D状态

运行在KVM虚拟机里的一些进程突然出了问题,这些出了问题的进程无法用kill杀掉,使用ps可以看到这些进程处于D状态:

[build@kbuild-john ~]$ ps -a -o pid,ppid,stat,command

PID PPID STAT COMMAND

17009 1 Ds -bash

17065 1 D ls --color=tty -al

17577 1 D /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a

17629 1 D /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a

ps 的手册里说D状态是uninterruptible sleep.

Linux进程有两种睡眠状态:

一种是interruptible sleep,处在这种睡眠状态的进程是可以通过给它发信号来唤醒的,比如发HUP信号给nginx的master进程可以让nginx重新加载配置文件而不需要重新启动nginx进程;

另外一种睡眠状态是uninterruptible sleep,处在这种状态的进程不接受外来的任何信号,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是”kill”, “kill -9″还是”kill -15″,因为它们压根儿就不受这些信号的支配。

进程为什么会被置于uninterruptible sleep状态呢?

处于uninterruptible sleep状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被 ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统已经不可访问了,我这里遇到的问题就是由 down掉的NFS服务器引起的。

正是因为得不到IO的相应,进程才进入了uninterruptible sleep状态,所以要想使进程从uninterruptible sleep状态恢复,就得使进程等待的IO恢复,比如如果是因为从远程挂载的NFS卷不可访问导致进程进入uninterruptible sleep状态的,那么可以通过恢复该NFS卷的连接来使进程的IO请求得到满足,除此之外,要想干掉处在D状态进程就只能重启整个Linux系统了。

看到有人说如果要想杀掉D状态的进程,通常可以去杀掉它的父进程(通常是shell,我理解的这种情况是在shell下直接运行的该进程,之后该进程转入了D状态),于是我就照做了,之后就出现了上面的状态:他们的父进程被杀掉了,但是他们的父进程PID都变成了1,也就是init进程,这下可如何是好?此时我这些D状态的进程已经影响到其他一些进程的运行,而已经无法访问的NFS卷又在段时间内无法恢复,那么,只好重新启动了,root不是玉皇大帝,也有无奈的时候。

跟czhang说起这个事,觉得Linux如果有这么一个专用的垃圾回收进程就好了:系统自动或者用户手动把僵尸进程,和比如之前我遇到的D状态进程的PPID设为这个垃圾回收进程,那么通过干掉这个垃圾回收进程来清理这些僵尸们,这样该有多美好…

长期生活在 Linux 环境里,渐渐地就有一种环保意识油然而生。比如,我们会在登录提示里写上“悟空,我跟你说过叫你不要乱扔东西,乱扔东西是不对的。哎呀我话没说完你怎么把棍子扔掉了?月光宝盒是宝物,乱扔它会污染环境,要是砸到小朋友怎么办?就算砸不到小朋友,砸到了花花草草也不好嘛...”;在用户缺省目录里放一个题为 “自觉保护环境 请勿堆放垃圾”的空文件,并用 chattr +i 设为不可修改;看到垃圾文件就立即扫入 /tmp 目录,然后发广播通知垃圾制造者自己去 /tmp 认领,且警告其下不为例...我们深知,系统环境的整洁有利于系统管理员保持良好的心情、清晰的思路和稳定的工作状态。

有一类垃圾却并非这么容易打扫,那就是我们常见的状态为D (Uninterruptible sleep),以及状态为 Z (Zombie)的垃圾进程。这些垃圾进程要么是求而不得,像怨妇一般等待资源(D),要么是僵而不死,像冤魂一样等待超度(Z),它们在 CPU run_queue 里滞留不去,把Load Average 弄的老高老高,没看过我前一篇blog的国际友人还以为这儿民怨沸腾又出了什么大事呢。怎么办?开枪!kill -9!看你们走是不走。但这两种垃圾进程偏偏是刀枪不入的,不管换哪种枪法都杀不掉它们。无奈,只好reboot,像剿灭禽流感那样不分青红皂白地一律扑杀!

悟空,我们所运维的可是24*7全天候对外部客户服务的系统,怎么能动不动就 reboot ?我们的考核指标可是4个9(99.99%,全年计划外当机时间不得超过52分钟34秒),又不是4个8,你稍微遇到点事就reboot,还要不要可用性了?再说,现在社会都开始奔和谐去了,我们对于 D 和 Z 这两种垃圾进程,也该尽可能采取慈悲手段,能解决其困难的,就创造条件,解决其实际困难,能消除其冤结的,就诵经烧纸,消除其前世冤结,具体问题应具体分析具体解决,滥杀无辜只会导致冤冤相报因果循环...

贫僧还是回来说正题。怨妇 D,往往是由于 I/O 资源得不到满足,而引发等待,在内核源码 fs/proc/array.c 里,其文字定义为“ "D (disk sleep)", /* 2 */ ”(由此可知 D 原是Disk的打头字母),对应着 include/linux/sched.h 里的“ #define TASK_UNINTERRUPTIBLE 2 ”。

举个例子,当 NFS 服务端关闭之时,若未事先 umount 相关目录,在 NFS 客户端执行 df 就会挂住整个登录会话,按Ctrl+C 、Ctrl+Z都无济于事。断开连接再登录,执行 ps axf 则看到刚才的 df 进程状态位已变成了 D ,kill -9 无法杀灭。正确的处理方式,是马上恢复 NFS 服务端,再度提供服务,刚才挂起的 df 进程发现了其苦苦等待的资源,便完成任务,自动消亡。若 NFS 服务端无法恢复服务,在 reboot 之前也应将 /etc/mtab 里的相关 NFS mount 项删除,以免 reboot 过程例行调用 netfs stop 时再次发生等待资源,导致系统重启过程挂起。

冤魂 Z 之所以杀不死,是因为它已经死了,否则怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有结未解之故。在UNIX/Linux中,每个进程都有一个父进程,进程号叫PID(Process ID),相应地,父进程号就叫PPID(Parent PID)。当进程死亡时,它会自动关闭已打开的文件,舍弃已占用的内存、交换空间等等系统资源,然后向其父进程返回一个退出状态值,报告死讯。如果程序有 bug,就会在这最后一步出问题。儿子说我死了,老子却没听见,没有及时收棺入殓,儿子便成了僵尸。在UNIX/Linux中消灭僵尸的手段比较残忍,执行 ps axjf 找出僵尸进程的父进程号(PPID,第一列),先杀其父,然后再由进程天子 init(其PID为1,PPID为0)来一起收拾父子僵尸,超度亡魂,往生极乐。注意,子进程变成僵尸只是碍眼而已,并不碍事,如果僵尸的父进程当前有要务在身,则千万不可贸然杀之。

关于ZOMBIE进程

这些进程已经死亡,但没有释放系统资源,包括内存和一些一些系统表等,如果这样的进程很多,会引发系统问题。用ps -el看出的进程状态如果是Z,就是僵尸进程。

ps -ef|grep defunc可以找出僵尸进程.

有些ZOMBIE进程时用kill -9也不能杀死,而且消耗了很多系统资源不能释放,如果系统在shutdown时发出信息:some process wouldn’t die. 这就意味这有些进程不能被reboot发出的kill –9杀掉,这些很可能就是僵尸进程。

可以用ps 的 – l 选项,得到更详细的进程信息.

F(Flag):一系列数字的和,表示进程的当前状态。这些数字的含义为:

00:若单独显示,表示此进程已被终止。

01:进程是核心进程的一部分,常驻于系统主存。如:    sched、 vhand 、bdflush 等。

02:Parent is tracing process.

04 :Tracing parent's signal has stopped the process; the parent is waiting ( ptrace(S)).

10:进程在优先级低于或等于25时,进入休眠状态,而且不能用信号唤醒,例如在等待一个inode被创建时

20:进程被装入主存(primary memory)

40:进程被锁在主存,在事务完成前不能被置换   e

S(state of? the process )

O:进程正在处理器运行  ms这个状态从来木见过, 倒是R常见

S:休眠状态(sleeping)

R:等待运行(runable)    R Running or runnable (on run queue) 进程处于运行或就绪状态

I:空闲状态(idle)

Z:僵尸状态(zombie)

T:跟踪状态(Traced)

B:进程正在等待更多的内存页

D:不可中断的深度睡眠,一般由IO引起,同步IO在做读或写操作时,cpu不能做其它事情,只能等待,这时进程处于这种状态,如果程序采用异步IO,这种状态应该就很少见到了

C(cpu usage):cpu利用率的估算值

清除ZOMBIE(僵尸)进程可以使用如下方法:

kill –18 PPID (PPID是其父进程)

这个信号是告诉父进程,该子进程已经死亡了,请收回分配给他的资源。

如果不行则看能否终止其父进程(如果其父进程不需要的话)。先看其父进程又无其他子进程,如果有,可能需要先kill其他子进程,也就是兄弟进程。方法是:

kill –15 PID1 PID2(PID1,PID2是僵尸进程的父进程的其它子进程)。

然后再kill父进程:kill –15 PPID 这样僵尸进程就可能被完全杀掉了。

如何杀掉D状态的进程?

基本想法就是修改内核,遍历进程列表,找到处于D状态的进程,将其状态转换为别的状态就可以kill掉了。

这是一种比较粗鲁的方法,可能会引起一些不良后果,暂时没有考虑。对于确切知道已经没有什么用处,不用做清理工作的,处于D状态怎么也杀不死的进程来说,确是很有效。

内核模块代码:

----------------killd.c----------------

#include

#include

#include //for_each_process

MODULE_LICENSE("BSD");

static int pid = -1;

module_param(pid, int, S_IRUGO);

static int killd_init(void)

{

struct task_struct * p;

printk(KERN_ALERT "killd: force D status process to death\n");

printk(KERN_ALERT "killd: pid=%d\n", pid);

//read_lock(&tasklist_lock);

for_each_process(p){

if(p->pid == pid){

printk("killd: found\n");

set_task_state(p, TASK_STOPPED);

printk(KERN_ALERT "killd: aha, dead already\n");

return 0;

}

}

printk("not found");

//read_unlock(&tasklist_lock);

return 0;

}

static void killd_exit(void)

{

printk(KERN_ALERT "killd: bye\n");

}

module_init(killd_init);

module_exit(killd_exit);

-----Makefile------------

obj-m := killd.o

编译模块

make -C yourkerneltree M=`pwd` modules

插入模块的时候提供D状态的进程号,就可以将其转换为stopped状态,使用普通kill就可以杀死。

./insmod ./killd.ko pid=1234

如何看各个状态的进程

进程级别

#ps axwf -eo pid,stat | grep D

线程级别

ps -eL -eo pid,stat,pcpu | grep D

linux top java进程状态_linux top进程状态D相关推荐

  1. linux top 命令可视化_Linux top命令使用详解:显示或管理执行中的程序

    top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具.通过top命令所提供的互动式界面,用热键可以管理. 语法 top(选项) 选项 -b:以批处理模式 ...

  2. linux 查看java进城_linux查看java进程|线程池信息

    1.根据端口号57638查看对应进程pid/name=1463/java netstat -apn | grep  57638 tcp        0      0 ::ffff:172.20.5. ...

  3. linux 查看java进程_Linux进程查看及管理工具(ps, vmstat, dstat, glances等)

    pstree pstree - display a tree of processes , 进程树查看. [root@localhost /]# pstree systemd─┬─agetty├─au ...

  4. linux查看java版本_linux 查看java版本

    inux查看java jdk安装路径和设置环境变量 windows: set java_home:查看JDK安装路径 java -version:查看JDK版本 linux: whereis java ...

  5. linux下java多线程_Linux系统下Java问题排查——cpu使用率过高或多线程锁问题

    原标题:Linux系统下Java问题排查--cpu使用率过高或多线程锁问题 一个系统.特别是多线程并发的后台系统,在某些特定场景下,可能触发系统中的bug:导致cpu一直居高不下.进程hang了或处理 ...

  6. linux查看java进程_linux查看java进程命令

    在linux系统下可以通过命令查看进程,那么具体是那个命令呢?下面由学习啦小编为大家整理了linux查看进程的命令,希望对大家有帮助! 一.linux查看进程的命令 有ps.pstree.pgrep等 ...

  7. linux 修改java版本_Linux 有问必答:如何在 Linux 中改变默认的 Java 版本

    提问:当我尝试在Linux中运行一个Java程序时,我遇到了一个错误.看上去像程序编译所使用的Java版本与我本地的不同.我该如何在Linux上切换默认的Java版本? 当Java程序编译时,编译环境 ...

  8. linux发布java网站_Linux下部署java web项目

    首先安装mysql 服务,可以参考我另外的一篇博客   centos7下部署mysql服务 Linux下的mysql是区分数据库表名的大小写的 修改 /etc/my.cnf 文件 在 [mysqld] ...

  9. linux 监控java内存_Linux下实用的JAVA内存泄露监控命令及工具

    一.Linux 命令 1.jstack (linux下特有) 可以观察到jvm中当前所有线程的运行情况和线程当前状态 jstack 2083 输出内容如下: 2.jmap (linux下特有,也是很常 ...

最新文章

  1. C#:将另一个应用程序的主窗口移至屏幕最前
  2. python之开发系列
  3. JAVE SE 学习day_09:sleep线程阻塞方法、守护线程、join协调线程同步方法、synchronized关键字解决多线程并发安全问题
  4. python 最小硬币数_程序以找到要在Python中达到目标的硬币组合数量
  5. 前端一HTML:七:css初步认识
  6. Arrays.sort()源码分析
  7. Android studio中获取按钮组的信息如何循环遍历
  8. Arduino文档阅读笔记-attachInterrupt()
  9. Android的内容观察者
  10. ZABBIX 3.2 基础安装
  11. 什么是AJAX (转贴)
  12. python 直方图的绘制方法全解_5种方法教你用Python玩转histogram直方图
  13. Chrom安装Axure插件浏览原型图
  14. 用纯CSS实现八卦太极图
  15. 量化投资学习——股指期货研究(五)
  16. android推箱子实验报告,android开发——推箱子小游戏(前序)
  17. java实现保龄球规则
  18. 最新版养猫小程序前端+后端搭建详细教程
  19. Delphi官方下载地址
  20. 树莓派下DS18B20获取实时温度

热门文章

  1. java7 新特性 总结版
  2. python爬虫之爬取时光网电影影评
  3. C4D常用14款插件
  4. Vue前端与Django后端实现前后端分离连接
  5. 我怀念的何止是那片土地
  6. Labelary Online ZPL Viewer
  7. 扩展标记语言-XML
  8. ORA-01950:表空间USERS中无权限的2种方法
  9. Maven相关内容学习笔记一:基本配置和使用
  10. 2022什么蓝牙耳机好用?适合618入手的无线蓝牙耳机推荐