开发者

linux进程D状态的解决思路分享

目录
  • 1. 问题描述
  • 2. 问题分析
  • 3. 实验模拟
    • 3.1 使用losetup创建一个卷作为pv的磁盘
    • 3.2 使用/dev/loop0块设备创建pv, vg和lv
    • 3.3 使用刚创建的lv
    • 3.4 dmsetup suspend 命令暂停 lv 同时进行IO
    • 3.5 对/var/log/messages日志文件进行分析
  • 4. 问题总节
    • 5. linux常见几种状态
      • 5.1 TASK_RUNNING:(R)
      • 5.2 TASK_INTERRUPTIBLE:(S)
      • 5.3 TASK_UNINTERRUPTIBLE:(D)
      • 5.4 EXIT_ZOMBIE:(Z)
    • 6. 关于SysRq
      • 6.1 什么是SysRq键?
      • 6.2 如何启用SysRq键
    • 总结

      1. 问题描述

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

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

      2. 问题分析

      在正常情况下,不间断状态只持续几分之一秒。但是,异常情况下,进程可能会停留在此状态更长的时间或(在最坏的情况下)无限期地停留。

      这种状态下,即使使用“kill -9”也无法杀死进程,因为在进程唤醒之前,kill信号无法传递给进程。

      3. 实验模拟

      在Centos 7.9环境模拟一个处于D状态的进程并进行实验分析:

      使用LVM卷的 suspend 特性,暂停IO,使得上层应用程序处于D状态。

      3.1 使用losetup创建一个卷作为pv的磁盘

      losetup命令概述

      losetup命令用来设置loop设备,loop设备可以将文件虚拟成块设备,这样用户就可以对其进行挂载,

      比如常见的ISO光盘镜像、img镜像都可以被虚拟成块设备,然后进行挂载和访问。

      # dd写入一个2G的文件
      $ dd GjlmRif=/dev/zero of=/tmp/diskfile count=2048 bs=1M
      # 将2G的文件虚拟成块设备
      $ losetup --show -f /tmp/diskfile

      linux进程D状态的解决思路分享

      3.2 使用/dev/loop0块设备创建pv, vg和lv

      [root@node-1 ~]# pvcreate /dev/loop0
        Physical volume "/dev/loop0" successfully created.
      [root@node-1 ~]# vgcreate vg01 /dev/loop0
        Volume group "vg01" successfully created
      [root@node-1 ~]# lvcreate -n lv01 -L 1G vg01
        Logical volume "lv01" created.

      3.3 使用刚创建的lv

      创建一个文件系统并挂载到/mnt目录

      [root@node-1 ~]# mkfs.ext4 /dev/vg01/lv01
      [root@node-1 ~]# mount /dev/vg01/lv01 /mnt

      linux进程D状态的解决思路分享

      3.4 dmsetup suspend 命令暂停 lv 同时进行IO

      [root@node-1 ~]# dmsetup suspend /dev/vg01/lv01 && dd if=/dev/urandom of=/mnt/iotest.img count=1024 bs=1M

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

      linux进程D状态的解决思路分享

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

      [root@node-1 ~]# ps -aux | awk '$8 == "D+" {print $0}'
      root       1685  0.0  0.0 108096   620 pts/0    D+   15:57   0:00 dd if=/dev/urandom of=/mnt/iotest.img count=1024 bs=1M

      通过kill -9 1685也杀死不掉该进程

      [root@node-1 ~]# kill -9 1685
      [root@node-1 ~]# ps -aux | awk '$8 == "D+" {print $0}'
      root  javascript     1685  0.0  0.0 108096   620 pts/0    D+   16:21   0:00 dd if=/dev/urandom of=/mnt/iotest.img count=1024 bs=1M

      3.5 对/var/log/messages日志文件进行分析

      看到“task dd:1685 blocked for more than 120 seconds.”这样的消息时,这通常意味着有一个名为dd的进程(进程ID为1685)在执行过程中被阻塞了超过120秒。

      linux进程D状态的解决思路分享

      但dd进程为什么会被堵塞我们也不知道,应需要开发人员去分析call trace信息。

      但由于这是通过测试模拟的,我知道是什么原因堵塞,所以我们通过dmsetup resume命令www.devze.com进行恢复lv, 然后dd命令io就正常写入了,进程状态也由D变为R 。

      [root@node-1 ~]# dmsetup resume /dev/vg01/lv01

      linux进程D状态的解决思路分享

      4. 问题总节

      1、如果生产环境遇到进程一直处于D状态,无法kill 掉, 重启服务器解决

      2GjlmR、运维侧分析日志或者事件升级到研发,找到进程处于D状态的原因,让进程从D状态恢复到R状态。

      通过sysrq工具进行手动从内核收集D进程信息转存到messages,拿到日志进一步分析或升级到研发分析:

      # 启用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,进行进一步分析

      5. linux常见几种状态

      这里只列出4种状态

      5.1 TASK_RUNNING:(R)

      进程当前正在运行,或者正在运行队列中等待调度。

      只有在该状态的进程才可能在CPU上运行,同一时刻可能有多个进程处于运行状态。

      5.2 TASK_INTERRUPTIBLE:(S)

      进程处于睡眠状态,处于这个状态的进程因为等待某事件的发生(比如等待socket连接、等待信号量),而被挂起。当这些事件发生时,对应的等待队列中的一个或多个进程将被唤醒。

      一般情况下,进程列表中的绝大多数进程都处于TASK_INTERRUPTIBLE状态。进程可以被信号中断。接收到信号或被显式的唤醒呼叫唤醒之后,进程将转变为TASK_RUNNING 状态。

      5.3 TASK_UNINTERRUPTIBLE:(D)

      不可中断的睡眠状态,此进程状态类似于 TASK_INTERRUPTIBLE,只是它不会处理信号。

      不可中断,指的是进程不响应异步信号,无法用kill命令关闭处于TASK_UNINTERRUPTIBLE状态的进程。

      5.4 EXIT_ZOMBIE:(Z)

      进程已终止,它正等待其父进程收集关于它的一些统计信息。

      不可被kill, 即不响应任务信号, 无法用SIGKILL杀死

      6. 关于SysRq

      6.1 什么是SysRq键?

      “SysRq”键也称为“Print Screen”键,按下SysRq键,LINUX内核会响应,除www.devze.com非内核完全崩溃。

      关于SysRq的参考链接:参考点这里

      6.2 如何启用SysRq键

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

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

      • 0 完全禁用 sysrq。
      • 1 启用 sysrq 的所有功能。
      • >1 允许的 sysrq 函数的位掩码

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新运维

      运维排行榜