什么叫进程被 D 了
来源丨经授权转自 闪客公众号
作者丨闪客
闪客:哈哈,这可不是骂人。不过这句话稍微有点歧义,有可能指进程被杀死了,但这么说会有点傻缺,还不如直接说进程被杀了。
小宇:啥?睡眠还能不可断?它睡得多死?
闪客:哈哈,是的,确实可以理解为“死睡”。简单来说,进程在访问某些资源,比如硬盘或者网络 IO 的时候,如果这些操作被阻塞了,它就会进入“D”状态。
小宇:哦,那为啥不直接叫“阻塞”呢?非得搞个“D”这么神秘。
闪客:这个简单,用 top 或者 ps 命令就行了。比如 ps aux 的输出里,你会看到有些进程的 STAT 列是“D”,这就是它进入不可中断睡眠状态的标志。扩展下,除了这个状态之外其他的进程状态可以在内核源码中找到。
小宇:明白了,但为啥进程会卡在这个状态上?它不动不响的,是不是就有问题了?
闪客:没错,正常的 D 状态是短暂的,比如一个程序在读写文件时可能会瞬间进入 D 状态,所以 ps 查看进程的时候一般很难抓到有 D 进程的画面。
小宇:哦,这么说的话,这种问题有可能是硬件的,也有可能是软件的对吧?
闪客:正解!比如有一次我遇到的情况是数据库进程死死地 D 在那儿,检查后发现是存储服务器出了问题。还有一次是有个进程执行 sync 系统调用同步写盘,但磁盘故障了一直写不进去,也是一直 D 在了那里。
小宇:听起来解决起来应该挺麻烦吧?
闪客:是的,尤其是 D 状态的进程是不能被 kill 掉的,因为它们在等资源,这个等待过程完全由内核控制。你只能从根源上解决问题,比如排查硬盘、网络或者锁的情况,找到卡住的地方。解决不了就只能重启了。
小宇:那有没有什么工具能帮我分析这种问题?
闪客:当然有啦!比如 dstat 可以实时监控 IO 和 CPU 的状态,iotop 可以帮你看具体哪个进程占用了最多的 IO。用 strace 或者 lsof 查看进程当前在干啥(但你进程啥都不响应了其实也没辙)。实在不行还可以直接看内核日志,用 dmesg 或者 journalctl 找线索。
小宇:这么一说还真挺复杂的啊。
闪客:对啊,所以当你听到有人说进程 D 了,不要慌,先查查它在干啥。如果是硬盘或者网络问题,就找运维大哥帮忙;如果解决不了,就说只能重启就好了,这是正确的解法,只不过容易被人误解为菜鸡。
小宇:你这么一讲,我突然感觉进程被 D 是一种不幸的宿命啊。
闪客:对,就像陷入了黑洞一样,死活没办法,只能重启。话说,今天技术聊得够多啦,咱一块吃个饭放松放松脑子吧。
小宇:不了,我现在脑子有点 D 了,打算回家睡觉去咯,下次吧。
