环境
红帽企业 Linux 4、5、6、7、8、9
问题
什么是“D”状态(或 dstate 或 d-state)?
什么是进程的“D”状态?
解决
Linux遵循传统UNIX的标准,将其平均负载计算为指定时间间隔内可运行或正在运行的进程(R状态)的平均数量,以及处于不间断睡眠(D状态)的进程数量。
“D”状态(TASK_UNINTERRUPTIBLE)是发生在内核代码路径中的一种状态,在该状态下,在处理任务时执行不能被中断。我们希望这个应该是一个短暂的过程,且在正常操作中内核线程应该快速地从 TASK_UNINTERRUPTIBLE 状态中出来。
“D”状态进程通常被阻塞等待资源,磁盘 IO 和锁是进程可能阻塞的几种常见资源。
一个例子可能是与硬件通信的 low level 驱动程序,可能从 NIC 固件检索网络数据包数据或访问硬盘驱动器上的数据块 - 读写 IO。
通常,这种情况发生得非常快,并且线程会在很短的时间内出现这种状态(因此通常不会观察到,尤其是在用户空间中)。
“D”状态名称有历史原因,因为最初认为这种状态是进程处于“磁盘等待”状态。但现在,网络、锁和其他与“磁盘 io”不同的资源也可能会使进程处于不可中断的等待状态。有关进程状态的更多背景信息,请参阅“了解 Linux 进程状态” 【1】。具体来说,我们总结了“D”状态过程如下:“不可中断睡眠状态是不会立即处理信号的状态。它只会在等待的资源变得可用或等待期间发生超时(如果在进程进入休眠状态时指定了超时)后唤醒。”
当线程进入“D”状态并且未能在合理的时间内退出该状态时,就会出现问题。该进程现在被“卡住”,任何等待它的进程(可能在队列中位于其后面以访问相同的硬件)或依赖它的进程也同样被卡住。
虽然“合理的时间”是主观的,但如果任务在 D 状态下停滞太久,则会输出“INFO: task <process>:<pid> blocked for more than 120 seconds”【2】消息,可以系统调整【3】来对超时时间做调整。
要查看哪个进程/线程保持在“D”状态:
获取处于“D”状态的线程列表:ps auxH | awk '$8 ~ /^D/{print}'
显示每个进程程的堆栈sudo cat /proc/<PID>/stack
for D_PID in $(ps auxH | awk '$8 ~ /^D/{print $2}');do ps -Llp $D_PID;sudo cat /proc/$D_PID/stack;echo;done
根本原因
发现进程处于 D 状态是相当常见和正常的
在大多数情况下,这是由于对 I/O 资源(通常是本地或远程存储、网络文件系统等)的访问中断造成的
如果进程在 D 状态下停留/停滞时间过长,则内核中的“停滞任务”【4】逻辑将被激活
诊断步骤
检查 ps 输出中是否有处于 D 状态的线程,可以使用类似于以下内容的内容:
ps auxH | awk '$8 ~ /^D/{print}'
负载可能很高并且不断增加(可能有成百甚至到数千,1 分钟负载始终高于 5 分钟,5 分钟始终高于 15 分钟,暗示报告的负载不断增加);机器的响应能力与这个高数字不匹配(机器还能响应命令,但是如果所有核心都被占据之后,可能系统就不再响应)
解决问题的第一步(假设前两个步骤得到了验证)是隔离导致这种情况的资源(最有可能的存储/文件系统),例如查看处于 d 状态(当前工作)的进程的共同使用的文件或者目录等
一旦确定了相关资源,就应采取措施恢复对其的访问;根据具体情况,可能可以重新获得在线文件系统/存储的访问权限,或者可能需要重新启动计算机才能完全恢复(最有可能)
参考:
【1】https://access.redhat.com/sites/default/files/attachments/processstates_20120831.pdf
【2】https://access.redhat.com/solutions/31453
【3】https://access.redhat.com/solutions/39188
【4】https://access.redhat.com/solutions/31453