Linux命令拾遺之理解系統負載(整理分享)

2022-01-10 19:01:27
本篇文章給大家帶來了Linux中負載的概念與問題診斷方法相關知識,其中包括了負載是什麼以及執行緒狀態等,希望對大家有幫助。

一般在類unix系統上,都會有系統負載(load average)這個指標,用來形容系統的繁忙程度,值越大則代表系統越繁忙。

檢視負載

$ uptime
19:59:57 up 29 days,  7:08,  1 user,  load average: 0.57, 0.26, 0.18

我們關注load average後的3個值,分別代表1分鐘、5分鐘、15分鐘的系統平均負載,如果1分鐘值>5分鐘值>15分鐘值,則代表近15分鐘內系統壓力越來越大,反之亦然。

同樣,在top命令的第一行,也能看到系統負載,它的含義和uptime是一樣的。

負載是什麼

一般來說,系統執行緒基本都在這3個狀態上:執行中,可執行,阻塞等待,其中,執行中的執行緒正在CPU上跑,可執行的執行緒等待CPU排程,而阻塞的執行緒等待鎖釋放或io完成。

在傳統unix系統上(如BSD),系統負載由正在執行的執行緒以及可執行的執行緒這2個部分組成。

它能很好的說明CPU的飽和情況,比如4核的CPU,如果負載一直高於4,那說明CPU資源飽和了。

而Linux擴大了負載的定義,如下:

Linux負載由正在執行的執行緒和可執行的執行緒,以及D狀態的執行緒(一般是等待io完成)這3個部分組成。

因為Linux認為,雖然D狀態的執行緒並不消耗CPU資源,但是它會消耗磁碟、網路卡等硬體資源以及鎖這樣的軟體資源,因此它也應該被用來計算系統負載,想來也合理,畢竟系統負載是用來描述整個系統的繁忙程度的,而不僅僅是CPU的。

執行緒狀態D

在Linux裡面,執行緒有如下常見狀態:

  • R: 正在執行或可執行狀態

  • S: 睡眠狀態,被阻塞等待喚醒

  • D: 不可中斷睡眠狀態,一般是等待io完成

這裡面的R與D狀態的執行緒會影響系統負載,因此,當系統負載較高時,可以通過如下命令瞭解是哪些執行緒導致的:

ps -eLo pid,tid,stat,comm | grep -E " R|D"

小實驗:將系統負載升到100

# 使用vfork函數建立一個子程序,子程序如果不呼叫exec系統呼叫,它的狀態會一直是D。

$ cat uninterruptible.c 
int main() {
    vfork();
    sleep(600);
    return 0;
}
# 編譯成可執行程式
$ gcc -o uninterruptible uninterruptible.c
# 執行100個程式
$ for i in {1..100}; do ./uninterruptible &; done

等待1分鐘,就會發現系統負載升到了快100,如下:

$ uptime
20:24:42 up 29 days,  7:32,  1 user,  load average: 99.94, 74.82, 35.87
# 可以看到很多D狀態的程序
$ ps -eLo pid,tid,stat,pcpu,wchan:32,comm | grep " D"
3774195 3774195 D     0.0 do_fork                          uninterruptible
3774196 3774196 D     0.0 do_fork                          uninterruptible
3774197 3774197 D     0.0 do_fork                          uninterruptible
3774198 3774198 D     0.0 do_fork                          uninterruptible

如上,通過ps命令可以看到執行緒狀態,還有一個wchan欄位,它顯示的是執行緒當前被阻塞在什麼核心函數上,這能看出一些蛛絲馬跡。

另外,通過/proc/sysrq-trigger可以看到D執行緒阻塞時的程式碼路徑,如下:

# 寫入一個w即可,需要root許可權執行
$ echo w > /proc/sysrq-trigger
# 然後核心會把D狀態執行緒呼叫棧輸出到核心紀錄檔,這可以通過dmesg檢視
$ dmesg

12.png

這裡就能很清楚的看到,是由於vfork系統呼叫引起的負載上升。

之前介紹過bcc工具集裡的offcputime工具,它可以用來繪製offcpu火焰圖,同樣的,診斷高負載問題時,也可以用這個工具,傳一個引數,讓其只關注D狀態執行緒的offcpu行為即可,如下:

# ubuntu安裝bcc工具集
$ sudo apt install bpfcc-tools
# 使用root身份進入bash
$ sudo bash
# --state 2用於指定抓取TASK_UNINTERRUPTIBLE即D狀態執行緒的offcpu棧
$ offcputime-bpfcc -K --state 2 -f 60  > d_state_offcpu_stack.out
# 繪製為offcpu火焰圖
$ awk '{ print $1, $2 / 1000 }' d_state_offcpu_stack.out | ./FlameGraph/flamegraph.pl --color=io --countname=ms > d_state_offcpu.svg

13.png

相關推薦:《Linux視訊教學

以上就是Linux命令拾遺之理解系統負載(整理分享)的詳細內容,更多請關注TW511.COM其它相關文章!