linux進(jìn)程D狀態(tài)的解決思路分享
1. 問(wèn)題描述
在Linux系統(tǒng)環(huán)境,進(jìn)程在內(nèi)核模式下等待I/O完成時(shí)通常會(huì)進(jìn)入不間斷睡眠狀態(tài),此時(shí)使用ps或top命令輸出的進(jìn)程顯示為D狀態(tài)。
當(dāng)然我們也可以使用sysrq工具將有關(guān)進(jìn)程的信息發(fā)送到/var/log/messages。
2. 問(wèn)題分析
在正常情況下,不間斷狀態(tài)只持續(xù)幾分之一秒。但是,異常情況下,進(jìn)程可能會(huì)停留在此狀態(tài)更長(zhǎng)的時(shí)間或(在最壞的情況下)無(wú)限期地停留。
這種狀態(tài)下,即使使用“kill -9”也無(wú)法殺死進(jìn)程,因?yàn)樵谶M(jìn)程喚醒之前,kill信號(hào)無(wú)法傳遞給進(jìn)程。
3. 實(shí)驗(yàn)?zāi)M
在CentOS 7.9環(huán)境模擬一個(gè)處于D狀態(tài)的進(jìn)程并進(jìn)行實(shí)驗(yàn)分析:
使用LVM卷的 suspend 特性,暫停IO,使得上層應(yīng)用程序處于D狀態(tài)。
3.1 使用losetup創(chuàng)建一個(gè)卷作為pv的磁盤(pán)
losetup命令概述
losetup命令用來(lái)設(shè)置loop設(shè)備,loop設(shè)備可以將文件虛擬成塊設(shè)備,這樣用戶(hù)就可以對(duì)其進(jìn)行掛載,
比如常見(jiàn)的ISO光盤(pán)鏡像、img鏡像都可以被虛擬成塊設(shè)備,然后進(jìn)行掛載和訪(fǎng)問(wèn)。
# dd寫(xiě)入一個(gè)2G的文件 $ dd if=/dev/zero of=/tmp/diskfile count=2048 bs=1M # 將2G的文件虛擬成塊設(shè)備 $ losetup --show -f /tmp/diskfile

3.2 使用/dev/loop0塊設(shè)備創(chuàng)建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 使用剛創(chuàng)建的lv
創(chuàng)建一個(gè)文件系統(tǒng)并掛載到/mnt目錄
[root@node-1 ~]# mkfs.ext4 /dev/vg01/lv01 [root@node-1 ~]# mount /dev/vg01/lv01 /mnt

3.4 dmsetup suspend 命令暫停 lv 同時(shí)進(jìn)行IO
[root@node-1 ~]# dmsetup suspend /dev/vg01/lv01 && dd if=/dev/urandom of=/mnt/iotest.img count=1024 bs=1M
此時(shí),該進(jìn)程就會(huì)處于D狀態(tài),命令不會(huì)返回到shell提示符。

可以通過(guò)另一個(gè) shell 終端來(lái)查看這個(gè)進(jìn)程:
[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通過(guò)kill -9 1685也殺死不掉該進(jìn)程
[root@node-1 ~]# kill -9 1685
[root@node-1 ~]# ps -aux | awk '$8 == "D+" {print $0}'
root 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=1M3.5 對(duì)/var/log/messages日志文件進(jìn)行分析
看到“task dd:1685 blocked for more than 120 seconds.”這樣的消息時(shí),這通常意味著有一個(gè)名為dd的進(jìn)程(進(jìn)程ID為1685)在執(zhí)行過(guò)程中被阻塞了超過(guò)120秒。

但dd進(jìn)程為什么會(huì)被堵塞我們也不知道,應(yīng)需要開(kāi)發(fā)人員去分析call trace信息。
但由于這是通過(guò)測(cè)試模擬的,我知道是什么原因堵塞,所以我們通過(guò)dmsetup resume命令進(jìn)行恢復(fù)lv, 然后dd命令io就正常寫(xiě)入了,進(jìn)程狀態(tài)也由D變?yōu)镽 。
[root@node-1 ~]# dmsetup resume /dev/vg01/lv01

4. 問(wèn)題總節(jié)
1、如果生產(chǎn)環(huán)境遇到進(jìn)程一直處于D狀態(tài),無(wú)法kill 掉, 重啟服務(wù)器解決
2、運(yùn)維側(cè)分析日志或者事件升級(jí)到研發(fā),找到進(jìn)程處于D狀態(tài)的原因,讓進(jìn)程從D狀態(tài)恢復(fù)到R狀態(tài)。
通過(guò)sysrq工具進(jìn)行手動(dòng)從內(nèi)核收集D進(jìn)程信息轉(zhuǎn)存到messages,拿到日志進(jìn)一步分析或升級(jí)到研發(fā)分析:
# 啟用sysrq的功能: $ echo 1 > /proc/sys/kernel/sysrq # 轉(zhuǎn)儲(chǔ)處于不可中斷(阻塞)狀態(tài)的任務(wù)。 $ echo w > /proc/sysrq-trigger # 將當(dāng)前任務(wù)列表及其信息轉(zhuǎn)儲(chǔ)到您的控制臺(tái)。 $ echo t > /proc/sysrq-trigger # 顯示所有活動(dòng) CPU 的堆?;厮荨? $ echo l > /proc/sysrq-trigger 這會(huì)將任務(wù)和線(xiàn)程信息轉(zhuǎn)儲(chǔ)到/var/log/messages,進(jìn)行進(jìn)一步分析
5. linux常見(jiàn)幾種狀態(tài)
這里只列出4種狀態(tài)
5.1 TASK_RUNNING:(R)
進(jìn)程當(dāng)前正在運(yùn)行,或者正在運(yùn)行隊(duì)列中等待調(diào)度。
只有在該狀態(tài)的進(jìn)程才可能在CPU上運(yùn)行,同一時(shí)刻可能有多個(gè)進(jìn)程處于運(yùn)行狀態(tài)。
5.2 TASK_INTERRUPTIBLE:(S)
進(jìn)程處于睡眠狀態(tài),處于這個(gè)狀態(tài)的進(jìn)程因?yàn)榈却呈录陌l(fā)生(比如等待socket連接、等待信號(hào)量),而被掛起。當(dāng)這些事件發(fā)生時(shí),對(duì)應(yīng)的等待隊(duì)列中的一個(gè)或多個(gè)進(jìn)程將被喚醒。
一般情況下,進(jìn)程列表中的絕大多數(shù)進(jìn)程都處于TASK_INTERRUPTIBLE狀態(tài)。進(jìn)程可以被信號(hào)中斷。接收到信號(hào)或被顯式的喚醒呼叫喚醒之后,進(jìn)程將轉(zhuǎn)變?yōu)門(mén)ASK_RUNNING 狀態(tài)。
5.3 TASK_UNINTERRUPTIBLE:(D)
不可中斷的睡眠狀態(tài),此進(jìn)程狀態(tài)類(lèi)似于 TASK_INTERRUPTIBLE,只是它不會(huì)處理信號(hào)。
不可中斷,指的是進(jìn)程不響應(yīng)異步信號(hào),無(wú)法用kill命令關(guān)閉處于TASK_UNINTERRUPTIBLE狀態(tài)的進(jìn)程。
5.4 EXIT_ZOMBIE:(Z)
進(jìn)程已終止,它正等待其父進(jìn)程收集關(guān)于它的一些統(tǒng)計(jì)信息。
不可被kill, 即不響應(yīng)任務(wù)信號(hào), 無(wú)法用SIGKILL殺死
6. 關(guān)于SysRq
6.1 什么是SysRq鍵?
“SysRq”鍵也稱(chēng)為“Print Screen”鍵,按下SysRq鍵,LINUX內(nèi)核會(huì)響應(yīng),除非內(nèi)核完全崩潰。
關(guān)于SysRq的參考鏈接:參考點(diǎn)這里
6.2 如何啟用SysRq鍵
在配置LINUX內(nèi)核時(shí),如果對(duì)CONFIG_MAGIC_SYSRQ配置Y選項(xiàng),完成內(nèi)核編譯后,可以通過(guò)/proc/sys/kernel/sysrq來(lái)調(diào)用SysRq 鍵調(diào)用的函數(shù)。
以下是 /proc/sys/kernel/sysrq 中支持的值列表:
- 0 完全禁用 sysrq。
- 1 啟用 sysrq 的所有功能。
- >1 允許的 sysrq 函數(shù)的位掩碼
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Ubuntu搭建web站點(diǎn)并發(fā)布公網(wǎng)訪(fǎng)問(wèn)詳細(xì)步驟(內(nèi)網(wǎng)穿透)
這篇文章主要給大家介紹了關(guān)于Ubuntu搭建web站點(diǎn)并發(fā)布公網(wǎng)訪(fǎng)問(wèn)(內(nèi)網(wǎng)穿透)的相關(guān)資料,內(nèi)網(wǎng)穿透是一種實(shí)現(xiàn)在外網(wǎng)任意地點(diǎn)訪(fǎng)問(wèn)內(nèi)網(wǎng)的方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
在CentOS 7中進(jìn)行磁盤(pán)分區(qū)的詳細(xì)步驟
在服務(wù)器管理和運(yùn)維過(guò)程中,磁盤(pán)分區(qū)是一項(xiàng)基礎(chǔ)且重要的操作,合理的磁盤(pán)分區(qū)可以提高數(shù)據(jù)存儲(chǔ)的安全性、高效性,方便系統(tǒng)管理與維護(hù),本文將詳細(xì)介紹在 CentOS 7 系統(tǒng)中進(jìn)行磁盤(pán)分區(qū)的具體步驟和方法,需要的朋友可以參考下2025-09-09
Ubuntu中Nginx的安裝與配置詳細(xì)說(shuō)明
本篇文章小編為大家介紹,Ubuntu中Nginx的安裝與配置詳細(xì)說(shuō)明。需要的朋友參考下2013-04-04
Linux內(nèi)核設(shè)備驅(qū)動(dòng)之內(nèi)核的時(shí)間管理筆記整理
今天小編就為大家分享一篇關(guān)于Linux內(nèi)核設(shè)備驅(qū)動(dòng)之內(nèi)核的時(shí)間管理筆記整理,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12

