一文让你应对 Linux 进程 "D" 状态


一文让你应对 Linux 进程 “D” 状态

环境

红帽企业 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 进程状态"。具体来说,我们总结了 "D" 状态过程如下:“不可中断睡眠状态是不会立即处理信号的状态。它只有在等待资源变得可用或者在等待期间发生超时(如果在进程进入睡眠时指定了超时)时才会被唤醒。”
  • 当线程进入 "D" 状态并且未能在合理的时间内退出该状态时,就会出现问题。这个进程现在被“卡住”,任何等待它的进程(可能在它后面的队列中访问相同的硬件)或依赖它的进程也同样被卡住。
  • 要查看哪个进程/线程保持在 "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 状态停滞太久,那么内核中的“停滞任务”逻辑将被启用

诊断步骤

  • 检查 ps 输出中是否有处于 D 状态的线程,可以使用类似于以下内容的内容:ps auxH | awk '$8 ~ /^D/{print}'
  • 负载可能很高而且还在增加(可能有成百甚至到数千,1 分钟负载始终高于 5 分钟,5 分钟始终高于 15 分钟,暗示报告的负载不断增加);机器的响应能力与这个高数字不匹配(机器还能响应命令,但是如果所有核心都被占据之后,可能系统就不再响应)
  • 解决问题的第一步(假设前两个步骤得到了验证)是隔离导致这种情况的资源(最有可能的存储/文件系统),例如查看处于 d 状态(当前工作)的进程的共同使用的文件或者目录等
  • 一旦确定了所涉及的资源,就应采取措施恢复对它的访问;根据具体情况,可能会重新获得对在线文件系统/存储的访问,或者可能需要重新启动机器才能完全恢复(最有可能的情况)

参考链接


文章作者: Pudding
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pudding !
  目录