實戰Linux進程狀態觀察:R、S、D、T、Z狀態詳解與實驗模擬

前言

????????在Linux系統中,進程狀態是系統管理和性能調優的核心知識。一個進程從誕生到終止,會經歷運行(R)、可中斷睡眠(S)、不可中斷睡眠(D)、停止(T)、僵尸(Z)等多種狀態。理解這些狀態的含義、觸發條件及觀察方法,是診斷進程掛起、資源泄漏等問題的關鍵。

目錄

一、進程狀態觀察詳解

1、運行狀態(R - Running/TASK_RUNNING)

示例觀察方法

1. 創建測試程序

2. 運行程序并觀察狀態

方法一:使用top命令

方法二:使用ps命令

2、可中斷睡眠(S - Interruptible Sleep/TASK_INTERRUPTIBLE)

3、不可中斷睡眠(D - Uninterruptible Sleep/TASK_UNINTERRUPTIBLE)

方法一:模擬磁盤I/O導致的D狀態

1. 創建測試腳本

2. 準備觀察環境

第一步:查看可用設備

第二步:創建掛載點目錄

第三步:執行掛載一個慢速存儲設備

第四步:驗證掛載

第五步:給腳本執行權限:

第六步:運行并觀察

4、停止狀態(T - Stopped/TASK_STOPPED)

5、跟蹤狀態(T - Tracing Stop)

1. 創建進程并進入跟蹤狀態

2. 使用調試器附加到進程

3. 觀察進程狀態

4. 狀態變化示例

5. 其他產生T狀態的場景(了解,不要求掌握)

6. 如何解除T狀態

6、僵尸狀態(Z - Zombie/EXIT_ZOMBIE)?

1. 創建僵尸進程的C程序

2. 編譯并運行程序

3. 觀察進程狀態

4. 預期觀察到的現象

5. 清理僵尸進程(后面會講解,現在先了解)

6. 僵尸進程的特點

7. 僵尸進程的危害

7、死亡狀態(X - Dead/EXIT_DEAD)

理解死亡狀態的特點

二、常見問題

三、總結


一、進程狀態觀察詳解

1、運行狀態(R - Running/TASK_RUNNING)

????????進程處于運行狀態(running)并不等同于正在執行。運行狀態意味著該進程要么正在CPU上運行,要么處于運行隊列中等待執行。因此,系統中可以同時存在多個R狀態的進程。

重點:

  • 所有可調度的運行狀態進程都會被放入運行隊列
  • 操作系統進行進程切換時,直接從運行隊列中選擇下一個要執行的進程
  • 單核CPU上同一時刻只有一個進程真正在CPU上運行
  • 其他R狀態的進程都在運行隊列中等待

  • 多核CPU上可以有多個進程同時處于"正在運行"狀態

示例觀察方法

1. 創建測試程序

創建一個簡單的CPU密集型程序來觀察R狀態:

// cpu_busy.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {printf("PID: %d\n", getpid());while(1) {// 空循環保持CPU占用}return 0;
}

編譯:

gcc cpu_busy.c -o cpu_busy

2. 運行程序并觀察狀態

方法一:使用top命令
  1. 在當前終端窗口運行程序:

    ./cpu_busy
  2. 在另一個終端窗口運行top:

top

在top界面中,按Shift + P按CPU使用排序、觀察STAT列,會顯示R狀態:

方法二:使用ps命令
ps aux | grep cpu_busy

輸出示例:

其中R+表示:

  • R:運行狀態

  • +:在前臺進程組中

2、可中斷睡眠(S - Interruptible Sleep/TASK_INTERRUPTIBLE)

????????一個進程處于淺度睡眠狀態(sleeping)表示它正在等待某個事件的完成。處于這種狀態的進程可以被隨時喚醒或終止(這種狀態也被稱為可中斷睡眠,即interruptible sleep)。

例如運行以下代碼:

#include <stdio.h>
#include <unistd.h>int main()
{printf("I am running... \n");sleep(100);return 0;
}

編譯并運行:?

????????在代碼中調用sleep函數休眠100秒期間,若用其他用戶查看進程狀態,會發現進程處于淺度睡眠狀態:

處于淺度睡眠狀態的進程可以被終止,使用kill命令即可強制結束該進程:

3、不可中斷睡眠(D - Uninterruptible Sleep/TASK_UNINTERRUPTIBLE)

????????當進程處于深度睡眠狀態(Disk Sleep)時,系統無法終止該進程,只能等待其自行喚醒。這種狀態也被稱為不可中斷睡眠狀態(Uninterruptible Sleep),通常發生在進程等待I/O操作完成時。

????????以磁盤寫入為例:當進程發起寫盤請求后,會進入深度睡眠狀態等待磁盤響應(如寫入成功/失敗的通知)。在此狀態下,即使系統也無法終止該進程,必須等待I/O操作完成。(又稱磁盤休眠狀態)

方法一:模擬磁盤I/O導致的D狀態

1. 創建測試腳本

創建一個會觸發磁盤I/O的腳本:

#!/bin/bash
# 保存為 disk_io_test.shecho "PID: $$"
echo "將模擬磁盤I/O操作..."# 向慢速設備(如U盤/NFS)寫入大量數據
dd if=/dev/zero of=/mnt/nfs/testfile bs=1M count=1024 2>/dev/nullecho "I/O操作完成"

2. 準備觀察環境

第一步:查看可用設備

lsblk  # 查看所有存儲設備

輸出示例:

????????根據lsblk?的輸出,可以看到我的系統只有一個虛擬磁盤設備(vda),沒有檢測到其他存儲設備。這是典型云服務器或虛擬機的配置。

  1. vda:虛擬磁盤(40GB)

  2. vda1:第一個分區(已掛載到根目錄?/

第二步:創建掛載點目錄

sudo mkdir /mnt/mydisk  # 創建一個新目錄作為掛載點

第三步:執行掛載一個慢速存儲設備

sudo mount /dev/vda1 /mnt/mydisk

第四步:驗證掛載

df -h  # 查看已掛載的文件系統

ls /mnt/mydisk  # 查看掛載的設備內容

第五步:給腳本執行權限:

chmod +x disk_io_test.sh

第六步:運行并觀察

  1. 在一個終端運行腳本:

    ./disk_io_test.sh

  2. 在另一個終端觀察進程狀態:

    watch -n 0.5 'ps aux | grep disk_io_test | grep -v grep'

????????命令剛啟動時的狀態,可能還未進入深度睡眠(D狀態),而如果進入深度睡眠(D狀態),會輸出示例,必須要有產生足夠的 I/O 壓力,才會實現(我模擬不了,大概看一下就行):

user  12345  0.0  0.0  12345  678 pts/1    D+   14:30   0:05 /bin/bash ./disk_io_test.sh

其中D+表示:

  • D:深度睡眠狀態(不可中斷)

  • +:前臺進程組

4、停止狀態(T - Stopped/TASK_STOPPED)

????????Linux系統可通過發送SIGSTOP信號將進程掛起為暫停狀態(Stopped),發送SIGCONT信號則可恢復被暫停的進程運行。

例如:

向某進程發送SIGSTOP信號后,該進程立即進入暫停狀態:

直到收到SIGCONT信號才會繼續執行:

5、跟蹤狀態(T - Tracing Stop)

1. 創建進程并進入跟蹤狀態

首先,我們需要創建一個可以被跟蹤的進程:

#include <stdio.h>
#include <unistd.h>int main() {printf("子進程PID: %d\n", getpid());while(1) {// 無限循環保持進程運行sleep(1);}return 0;
}

編譯并運行這個程序,記下它的PID:

2. 使用調試器附加到進程

在另一個終端中,使用gdb附加到該進程:

sudo gdb -p <PID>

使用第三個終端觀察,此時,被調試的進程會進入T (Tracing Stop)狀態:

3. 觀察進程狀態

在第三個終端中,查看進程狀態:

ps -o pid,state,cmd -p <PID>

輸出可能類似于:

4. 狀態變化示例

  • 初始狀態:進程正常運行,狀態為"S"(睡眠)

  • 附加調試器后:狀態變為"T"(被跟蹤)

  • 繼續執行:在gdb中輸入"continue",狀態可能變回"S"

  • 斷點命中:當遇到斷點時,狀態再次變為"T"

5. 其他產生T狀態的場景(了解,不要求掌握)

  1. 使用strace跟蹤系統調用

    strace -p <PID>
  2. 使用ptrace系統調用Ptrace 詳解 - tangr206 - 博客園

    // 跟蹤進程的示例代碼
    ptrace(PTRACE_ATTACH, pid, NULL, NULL);
  3. 接收到SIGSTOP信號

    kill -SIGSTOP <PID>

6. 如何解除T狀態

  • 在gdb中:使用detach命令或退出gdb

  • 對于strace:按Ctrl+C終止strace

  • 對于SIGSTOP:發送SIGCONT信號

    kill -SIGCONT <PID>

6、僵尸狀態(Z - Zombie/EXIT_ZOMBIE)?

1. 創建僵尸進程的C程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid == 0) {int cnt=60;while(cnt--){// 子進程printf("子進程 PID: %d 開始運行\n", getpid());sleep(2);  // 模擬子進程工作printf("子進程 PID: %d 即將退出\n", getpid());}exit(0);   // 子進程退出} else if (pid > 0) {// 父進程printf("父進程 PID: %d 創建了子進程 %d\n", getpid(), pid);printf("父進程將不調用wait(),故意制造僵尸進程\n");// 父進程不調用wait(),繼續運行while(1) {sleep(1);printf("父進程仍在運行...\n");}} else {perror("fork失敗");exit(1);}return 0;
}

2. 編譯并運行程序

gcc -o zombie zombie.c
./zombie

3. 觀察進程狀態

重新運行,然后在另一個終端窗口中,使用以下命令觀察進程狀態變化:

watch -n 1 'ps -eo pid,ppid,state,cmd | grep -E "PID|zombie"'

4. 預期觀察到的現象

  1. 初始階段:父子進程都處于運行狀態(S)

  2. 子進程退出后

    • 子進程狀態變為Z(僵尸)

    • 父進程仍在運行

  3. 最終狀態

5. 清理僵尸進程(后面會講解,現在先了解)

要清理僵尸進程,可以:

  1. 終止父進程:

    kill -9 <父進程PID>
  2. 或者修改程序讓父進程調用wait():

    // 在父進程代碼中添加
    wait(NULL);  // 回收子進程

6. 僵尸進程的特點

  • 出現在進程表中,占用一個PID

  • 已釋放大部分資源,僅保留退出狀態等信息

  • PPID為創建它的父進程

  • 命令顯示為[進程名] <defunct>

  • 只能通過終止父進程或讓父進程調用wait()來清除

7. 僵尸進程的危害

  • 僵尸進程的退出狀態必須一直維持下去,因為它要告訴其父進程相應的退出信息。可是父進程一直不讀取,那么子進程也就一直處于僵尸狀態。
  • 僵尸進程的退出信息被保存在task_struct(PCB)中,僵尸狀態一直不退出,那么PCB就一直需要進行維護。
  • 若是一個父進程創建了很多子進程,但都不進行回收,那么就會造成資源浪費,因為數據結構對象本身就要占用內存。
  • 僵尸進程申請的資源無法進行回收,那么僵尸進程越多,實際可用的資源就越少,也就是說,僵尸進程會導致內存泄漏。

7、死亡狀態(X - Dead/EXIT_DEAD)

????????死亡狀態(X)是進程的最終狀態,表示進程已經完全終止且其資源已被系統回收。由于這個狀態持續時間極短(幾乎是瞬時的),直接觀察非常困難。

理解死亡狀態的特點

  • 瞬時性:X狀態是進程從退出到完全消失之間的瞬時狀態

  • 不可見性:通常無法通過ps等工具直接觀察到

  • 前驅狀態:進程通常從Z(僵尸)狀態轉為X狀態


二、常見問題

  1. 僵尸進程積累

    • 原因:父進程未正確處理子進程退出。

    • 解決:找到父進程ID(PPID)并重啟或發送SIGCHLD信號。

  2. 不可中斷進程卡住

    • 可能原因:硬件故障(如磁盤壞塊)、內核Bug。

    • 排查:dmesg查看內核日志,檢查硬件健康。

  3. 高負載下RUNNING進程過多:使用vmstat 1mpstat -P ALL 1分析CPU競爭。

  4. SD狀態的區別:S可被信號中斷,D必須等待事件完成(即使發送kill -9無效)。

  5. 為什么進程長時間處于D狀態?

  • 可能原因:硬件故障(如磁盤損壞)、內核驅動Bug。

  • 解決方案:檢查dmesg日志,修復硬件或更新驅動。


三、總結

  • 理解進程狀態是系統調優和故障排查的基礎。

  • R/S/D是常見狀態,Z需及時處理,T常用于調試。

  • 結合pstop/proc等工具實時監控狀態變化。

????????掌握這些狀態及其轉換機制,能有效診斷進程掛起、資源泄漏等問題。實際應用中需結合日志和性能工具(如straceperf)深入分析。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/913581.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/913581.shtml
英文地址,請注明出處:http://en.pswp.cn/news/913581.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫與關系數據庫的區別是什么

數據庫&#xff0c;簡單來說&#xff0c;就是一個存儲數據的地方&#xff0c;就像一個超級大倉庫&#xff0c;能把各種各樣的數據都收納進來。它可以是一個簡單的文本文件&#xff0c;用來記錄一些基本信息&#xff1b;也可以是一個復雜的系統&#xff0c;存儲著企業的大量業務…

如何解決微信小程序出現兩個下拉刷新樣式?

在微信小程序中&#xff0c;如果出現兩個下拉刷新的情況&#xff0c;可能是因為在多個地方啟用了下拉刷新功能&#xff0c;或者在同一個頁面中多次調用了下拉刷新的API。以下是一些可能的原因和解決方法&#xff1a; 多次調用下拉刷新API&#xff1a; 確保在頁面的生命周期中只…

(3)手摸手-學習 Vue3 之 變量聲明【ref 和 reactive】區別

手摸手-學習 Vue3 之 變量聲明【ref 和 reactive】區別前言ref 擴展ref 和 reactive 區別前言 ref 擴展 在之前博文《&#xff08;2&#xff09;手摸手-學習 Vue3 之 變量聲明【ref 和 reactive】》中有提到&#xff1a; 當時已基本類型 進行演練說明&#xff0c;此時以 對象…

機器視覺運動控制一體機在SCARA機器人柔振盤上下料的應用

市場應用背景 SCARA機器人是一種高效、高精度的圓柱坐標系工業機器人&#xff0c;專精于裝配任務。其獨特的機械結構賦予其在特定方向&#xff08;通常是XY平面&#xff09;高度順應性&#xff0c;同時在垂直方向保持優異剛性。 SCARA機器人本體通常包含三個軸線平行的旋轉關…

3D 演示動畫在汽車培訓與教育領域中的應用

在企業培訓這一至關重要的領域中&#xff0c;3D 演示動畫猶如一顆璀璨的明星&#xff0c;發揮著無可替代的關鍵作用&#xff0c;大顯身手。以某知名汽車制造企業為例&#xff0c;當對新入職員工開展汽車裝配培訓工作時&#xff0c;企業精心利用先進的 3D 演示動畫技術制作了極為…

華銳視點 VR 污水處理技術對激發學習興趣的作用?

華銳視點的 VR 虛擬仿真平臺&#xff0c;尤其是 VR 污水處理模塊&#xff0c;不僅僅是讓學生觀察&#xff0c;還設置了豐富多樣的互動操作環節&#xff0c;充分激發學生的學習興趣和主動性。?在平臺的 VR 污水處理模擬中&#xff0c;學生可以模擬操作各種污水處理設備。比如&a…

百度斬獲大模型中標第一,股價上漲5%

7月7日&#xff08;周一&#xff09;&#xff0c;百度&#xff08;BIDU.US&#xff09;股價上漲 5%&#xff0c;收報 90.68美元。最新數據顯示&#xff0c;2025上半年我國大模型相關項目呈現爆發式增長態勢&#xff1a;中標項目累計達 1810個&#xff0c;金額突破 64億元&#…

【計算機網絡】4網絡層②

概念是什么?以太網有線聯網的標準LAN小范圍網絡(家里/公司)WAN大范圍網絡(跨城市)Internet全球公共互聯網 ??internet任意互聯的網絡 ??子網將一個LAN通過路由器的硬件隔離分為多個LAN(廣播域)VLAN將一個LAN通過交換機的軟件方法分為多個VLAN(廣播域)以太網和Wi-Fi建L…

微信小程序81~90

1. 配置分包加載以及打包、引用原則 小程序如果需要進行分包加載&#xff0c;需要在 app.json 中&#xff0c;通過 subPackages 或者 subpackages 定義分包結構 每個分包結構含三個常用字段&#xff1a; root&#xff1a;分包的根目錄&#xff0c;該目錄下的所有文件都會被打包…

深度學習——神經網絡1

一、神經網絡 1.神經網絡定義&#xff1a;人工神經網絡&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;也簡稱為神經網絡&#xff08;NN&#xff09;&#xff0c;是一種模仿生物神經網絡結構和功能的計算模型。人腦可以看作是一個生物神經網絡&#xff0c;由…

ipmitool 使用簡介(ipmitool sel list ipmitool sensor list)

常用IPMI命令擴展使用ipmitool查看傳感器信息ipmitool是一個用于管理IPMI&#xff08;Intelligent Platform Management Interface&#xff09;設備的命令行工具&#xff0c;可用于監控服務器硬件狀態&#xff0c;包括傳感器數據。運行以下命令可以列出所有傳感器信息&#xff…

小米YU7預售現象深度解析:智能電動汽車的下一個范式革命

小米YU7預售現象深度解析&#xff1a;智能電動汽車的下一個范式革命一、預售數據創造三項行業新紀錄 2025年6月26日的小米YU7發布會&#xff0c;不僅刷新了智能汽車預售速度&#xff0c;更揭示了新時代的消費心理變遷&#xff1a; &#xff08;1&#xff09;訂單爆發速度史無前…

xlog-Android15適配之16KB對齊

背景 前兩天查看Google play控制臺突然發現有告警&#xff0c;一看原來是要求必須盡快適配Android15。 過程 先看了一下網上的資料&#xff0c;Android15適配 發現對我的apk基本上沒有什么影響&#xff0c;除了 動態庫必須16KB對齊這一項。 最簡單查看apk是否16KB對齊的方法…

Crazyflie支持MATLAB/Simulink控制 基于NOKOV度量動捕系統實現

Crazyflie支持MATLABSimulink控制 基于NOKOV度量動捕系統實現 一、動捕軟件VRPN配置 以動捕軟件版本XINGYING 4.2.0.5495為例&#xff0c;其他版本同理。打開動捕軟件&#xff0c;連接上鏡頭。單擊菜單欄下的視圖->數據廣播。在數據廣播中的VRPN流下&#xff0c;將單位下拉…

Windows 系統安裝與使用 Claude Code 全攻略

Claude Code 作為一款高效的 AI 編程輔助工具&#xff0c;深受開發者青睞&#xff0c;但由于其本身不支持 Windows 文件系統&#xff0c;在 Windows 系統上使用需要借助 WSL&#xff08;適用于 Linux 的 Windows 子系統&#xff09;。下面為你詳細介紹在 Windows 系統上安裝和使…

如何用Python編程計算權重?

1. 加權平均中的權重計算&#xff08;已知權重值&#xff09; 如果已知各元素的權重&#xff0c;直接用權重乘以對應值后求和。 # 示例&#xff1a;計算加權平均分&#xff08;權重之和為1&#xff09; scores [80, 90, 70] # 各項分數 weights [0.3, 0.5, 0.2] # 對應權重…

WinUI3入門16:Order自定義排序

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C的&#xff0c;可以在任何平臺上使用。 源碼指引&#xff1a;github源…

Java 面向對象三大特性詳解:封裝、繼承與多態,掌握OOP核心思想

作為一名Java開發工程師&#xff0c;你一定知道&#xff0c;封裝&#xff08;Encapsulation&#xff09;、繼承&#xff08;Inheritance&#xff09;和多態&#xff08;Polymorphism&#xff09; 是面向對象編程&#xff08;Object-Oriented Programming, OOP&#xff09;的三大…

WPS中配置MathType教程

項目場景&#xff1a;在WPS中使用MathType問題描述&#xff1a;MathPage.wll或MathType.dll文件找不到問題原因分析&#xff1a;在C盤wps中的startup中有mathpage.wll,但配置不可用而我的WPS安裝在E盤&#xff0c;并且桌面圖標啟動路徑也是E盤路徑下的WPS路徑&#xff0c;所以不…

基于模板設計模式開發優惠券推送功能以及對過期優惠卷進行定時清理

1.模板設計模式&#xff1a;模板設計模式是一種常見的設計模式&#xff0c;主要作用是對 具體操作的 共有代碼塊進行提取&#xff0c;提升代碼復用性。那么說道代碼復用性&#xff0c;首先想到的是抽象類而不是接口。因為抽象類的本質就是為了代碼復用&#xff0c;抽象類既可以…