LINUX云服务器进程D状态问题分析

举报
云技术搬运工 发表于 2021/09/15 16:44:13 2021/09/15
【摘要】 问题描述 在Linux系统环境,进程在内核模式下等待I/O完成时通常会进入不间断睡眠状态,此时使用ps或top命令输出的进程显示为D状态。我们也可以使用sysrq工具将有关进程的信息发送到/var/log/messages。

问题描述

在Linux系统环境,进程在内核模式下等待I/O完成时通常会进入不间断睡眠状态,此时使用ps或top命令输出的进程显示为D状态。

1.png

问题分析

在正常情况下,不间断状态只持续几分之一秒。但是,异常情况下,进程可能会停留在此状态更长的时间或(在最坏的情况下)无限期地停留。这种状态下,即使使用“kill -9”也无法杀死进程,因为在进程唤醒之前,kill信号无法传递给进程。

要确定进程不可中断的原因,就需要找出进程正在等待什么的更多信息。

从RHEL5.5 版开始,RHEL包含一个内核线程,用于监视停留在D状态超过指定超时时间的进程。默认情况下,超时时间为120秒,可以使用内核参数 kernel.hung_task_timeout 修改或禁用它。当检测到此类进程时,该内核线程将有关该进程的信息(包括其内核堆栈跟踪)转储到 /var/log/messages。 2.png

我们也可以使用sysrq工具将有关进程的信息发送到/var/log/messages。

 

实验模拟

在CentOS 8.2环境模拟一个处于D状态的进程并进行实验分析:使用LVM卷的 suspend 特性,暂停IO,使得上层应用程序处于D状态。

(1)使用losetup创建一个卷作为pv的磁盘。

# dd if=/dev/zero of=/tmp/diskfile count=2048 bs=1M

# losetup --show -f /tmp/diskfile

3.png

(2)使用/dev/loop0创建pv, vglv

# pvcreate /dev/loop0

# vgcreate vg01 /dev/loop0

# lvcreate -n lv01 -L 1G vg01

4.png

(3)在lv上创建一个文件系统并挂载到/mnt目录。

# mkfs.ext4 /dev/vg01/lv01

# mount /dev/vg01/lv01 /mnt

 5.png(4)写IO同时暂停 lv

# dmsetup suspend /dev/vg01/lv01 && dd if=/dev/urandom of=/mnt/iotest.img count=1024 bs=1M

6.png

此时,该进程就会处于D状态,命令不会返回到shell提示符。

可以通过另一个 shell 终端来查看这个进程:

# ps axl | awk ‘$10 ~ /D/’ 7.png(5)分析/var/log/messages日志文件。

在当前实验场景,我们通过暂停进程使用的lv,使进程的IO操作发生阻塞,模拟出D进程现象。我们从/var/log/messages也看到了较为详细的相关日志信息。  8.png

在实际生产环境中,当出现D进程时,进程无法被杀死,通常需要重新启动系统来解决问题。/var/log/messages日志中也并不一定会有相关日志信息输出。这时我们可以使用sysrq工具手动从内核收集D进程信息,以进行问题分析。

# less /var/log/messages

我们依旧在当前实验环境使用sysrq工具进行手动从内核收集D进程信息的实验操作:

启用sysrq的功能:

# echo 1 > /proc/sys/kernel/sysrq

转储处于不可中断(阻塞)状态的任务。

# echo w > /proc/sysrq-trigger

将当前任务列表及其信息转储到您的控制台。

# echo t > /proc/sysrq-trigger

显示所有活动 CPU 的堆栈回溯。

# echo l > /proc/sysrq-trigger

这会将任务和线程信息转储到/var/log/messages:9.png

问题解决

将任务和线程信息转储到/var/log/messages,恢复lvIO

# dmsetup resume /dev/vg01/lv01

恢复LVIO后,进程状态也由D变为R  10.png 

    背景知识

    1、LINUX进程的几种状态:

1TASK_RUNNING:(R

进程当前正在运行,或者正在运行队列中等待调度。只有在该状态的进程才可能在CPU上运行,同一时刻可能有多个进程处于运行状态。

2TASK_INTERRUPTIBLE(S)

进程处于睡眠状态,处于这个状态的进程因为等待某事件的发生(比如等待socket连接、等待信号量),而被挂起。当这些事件发生时,对应的等待队列中的一个或多个进程将被唤醒。一般情况下,进程列表中的绝大多数进程都处于TASK_INTERRUPTIBLE状态。进程可以被信号中断。接收到信号或被显式的唤醒呼叫唤醒之后,进程将转变为TASK_RUNNING 状态。

3TASK_UNINTERRUPTIBLE(D)

不可中断的睡眠状态,此进程状态类似于 TASK_INTERRUPTIBLE,只是它不会处理信号。不可中断,指的是进程不响应异步信号,无法用kill命令关闭处于TASK_UNINTERRUPTIBLE状态的进程。

4TASK_STOPPED

进程已中止执行,它没有运行,并且不能运行。接收到 SIGSTOP  SIGTSTP 等信号时,进程将进入这种状态。接收到 SIGCONT 信号之后,进程将再次变得可运行。

5TASK_TRACED(T)

正被调试程序等其他进程监控时,进程将进入这种状态。

6EXIT_ZOMBIE(Z)

进程已终止,它正等待其父进程收集关于它的一些统计信息。不可被kill, 即不响应任务信号, 无法用SIGKILL杀死

7EXIT_DEAD(X)

最终状态(正如其名)。将进程从系统中删除时,它将进入此状态,因为其父进程已经通过 wait4()  waitpid() 调用收集了所有统计信息。EXIT_DEAD状态是非常短暂的,几乎不可能通过ps命令捕捉到。

8TASK_KILLABLE

Linux® kernel 2.6.25 引入了这种进程状态,用于将进程置为睡眠状态,它可以替代有效但可能无法终止的 TASK_UNINTERRUPTIBLE 进程状态,以及易于唤醒但更加安全的 TASK_INTERRUPTIBLE 进程状态。

     2、关于SysRq:

1)什么是SysRq键?

SysRq”键也称为“Print Screen”键,按下SysRq键,LINUX内核会响应,除非内核完全崩溃。关于SysRq的参考链接:https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html

2)如何启用SysRq键:

在配置LINUX内核时,如果对CONFIG_MAGIC_SYSRQ配置Y选项,完成内核编译后,可以通过/proc/sys/kernel/sysrq来调用SysRq 键调用的函数。

以下是 /proc/sys/kernel/sysrq 中支持的值列表:

  • 完全禁用 sysrq。
  • 启用 sysrq 的所有功能。
  • >1 允许的 sysrq 函数的位掩码(有关详细的函数说明,请参见下文):

2 =   0x2 - enable control of console logging level

4 =   0x4 - enable control of keyboard (SAK, unraw)

8 =   0x8 - enable debugging dumps of processes etc.

16 =  0x10 - enable sync command

32 =  0x20 - enable remount read-only

64 =  0x40 - enable signalling of processes (term, kill, oom-kill)

128 =  0x80 - allow reboot/poweroff

256 = 0x100 - allow nicing of all RT tasks

您可以通过以下命令在文件中设置值:

echo "number" >/proc/sys/kernel/sysrq

注意: /proc/sys/kernel/sysrq的值仅影响通过键盘进行的调用;/proc/sysrq-trigger则允许通过命令进行操作(需要具有管理员权限)。/proc/sysrq-trigger支持的命令及对应的功能如下:

 

命令

功能

b

将立即重新启动系统而不同步或卸载您的磁盘。

c

如果配置,将执行系统崩溃并进行故障转储。

d

显示持有的所有锁。

e

向除 init 之外的所有进程发送 SIGTERM。

f

将调用 oom 杀手来杀死一个内存占用进程,但如果没有任何东西可以杀死,请不要惊慌。

g

由 kgdb(内核调试器)使用

h

将显示帮助(实际上,此处列出的任何其他键都将显示帮助。但h很容易记住:-)

i

向除 init 之外的所有进程发送 SIGKILL。

j

强行“解冻” - 文件系统被 FIFREEZE ioctl 冻结。

k

安全访问密钥 (SAK) 杀死当前虚拟控制台上的所有程序。注意:请参阅下面 SAK 部分中的重要注释。

l

显示所有活动 CPU 的堆栈回溯。

m

将当前内存信息转储到您的控制台。

n

用于使 RT 任务变得很好

o

将关闭您的系统(如果已配置和支持)。

p

将当前的寄存器和标志转储到您的控制台。

q

将转储每个 CPU 的所有武装 hrtimer 列表(但不是常规 timer_list 计时器)以及有关所有时钟事件设备的详细信息。

r

关闭键盘原始模式并将其设置为 XLATE。

s

将尝试同步所有已安装的文件系统。

t

将当前任务列表及其信息转储到您的控制台。

u

将尝试以只读方式重新挂载所有已挂载的文件系统。

v

强制恢复帧缓冲控制台。

v

导致 ETM 缓冲区转储 [ARM 特定]

w

转储处于不可中断(阻塞)状态的任务。

x

由 ppc/powerpc 平台上的 xmon 接口使用。在 sparc64 上显示全局 PMU 寄存器。转储 MIPS 上的所有 TLB 条目。

y

显示全局 CPU 寄存器 [SPARC-64 特定]。

z

转储 ftrace 缓冲区。

0——9

设置控制台日志级别,控制将打印到控制台的内核消息。(0,例如,将使得只有像 PANICs 或 OOPSes 这样的紧急消息才能发送到您的控制台。)

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。