為什么用ps -l?因?yàn)槟J(rèn)的ps命令只能顯示進(jìn)程信息,而ps -l可以將線程作為獨(dú)立條目列出,便于查看每個(gè)線程的狀態(tài)、id及調(diào)度情況。如何理解輸出中的關(guān)鍵字段?pid是主進(jìn)程id,所有線程相同;lwp是線程id,即內(nèi)核層面的標(biāo)識(shí)符;%cpu和%mem表示資源占用;time+為累計(jì)運(yùn)行時(shí)間;command為啟動(dòng)命令。結(jié)合其他工具定位具體線程的方法包括:將lwp轉(zhuǎn)為16進(jìn)制用于gdb或jstack查找;使用jstack查看Java程序堆棧并匹配nid;通過top -h -p查看實(shí)時(shí)狀態(tài)。常見問題與注意事項(xiàng)有:權(quán)限不足需用sudo;線程多可加–sort=-cpu排序;lwp與tid等同。掌握這些技巧即可高效分析linux中進(jìn)程的子線程狀態(tài)。
在linux系統(tǒng)中,查看進(jìn)程的子線程信息是排查程序行為、調(diào)試多線程應(yīng)用時(shí)非常常見的需求。ps -L命令是一個(gè)簡(jiǎn)單直接的方法,它可以顯示某個(gè)進(jìn)程的所有線程信息。
為什么用 ps -L?
默認(rèn)的ps命令只會(huì)顯示進(jìn)程級(jí)別的信息,不會(huì)列出各個(gè)線程。而使用-L選項(xiàng)后,ps會(huì)把線程也作為獨(dú)立的條目列出來,方便你看到每個(gè)線程的狀態(tài)、ID以及調(diào)度情況。
比如你想查看PID為1234的進(jìn)程的所有線程:
ps -L -p 1234
輸出大致如下:
UID PID LWP %CPU %MEM TIME+ COMMAND user 1234 1234 0.0 0.1 0:00.00 app user 1234 1235 0.1 0.1 0:00.01 app user 1234 1236 0.0 0.1 0:00.00 app
其中LWP(Light Weight Process)就是線程的ID。
如何理解輸出中的關(guān)鍵字段?
- PID:主進(jìn)程ID,所有線程都屬于同一個(gè)進(jìn)程,所以這個(gè)值都一樣。
- LWP:線程ID,可以看作是內(nèi)核層面的線程標(biāo)識(shí)符,和用戶態(tài)的pthread ID不同。
- %CPU / %MEM:當(dāng)前線程占用的CPU和內(nèi)存資源。
- TIME+:線程已經(jīng)運(yùn)行的累計(jì)時(shí)間。
- COMMAND:?jiǎn)?dòng)線程的命令或程序名。
如果你需要更詳細(xì)的信息,比如線程狀態(tài)(R/S/D等),可以加上-o自定義輸出字段:
ps -L -p 1234 -o pid,lwp,stat,cpu,mem,comm
這樣可以看到線程的運(yùn)行狀態(tài),有助于判斷是否有線程卡死或者異常。
結(jié)合其他工具定位具體線程
雖然ps -L能列出線程信息,但通常我們還需要進(jìn)一步分析這些線程到底在做什么。這時(shí)候可以結(jié)合以下方式:
-
將LWP轉(zhuǎn)換為16進(jìn)制,用于gdb或jstack中查找:
printf "%xn" <lwp_id>
-
查看線程堆棧(適用于Java程序):
使用jstack
,然后查找對(duì)應(yīng)的nid(即線程ID的16進(jìn)制表示)。 -
查看線程詳細(xì)狀態(tài):
top -H -p 1234
這個(gè)命令會(huì)讓你看到每個(gè)線程的實(shí)時(shí)資源消耗。
常見問題與注意事項(xiàng)
-
權(quán)限不足看不到線程信息?
確保你有查看目標(biāo)進(jìn)程的權(quán)限,必要時(shí)可以用sudo。
-
線程太多導(dǎo)致輸出混亂?
可以加–sort=-cpu按CPU使用率排序,快速定位熱點(diǎn)線程:
ps -L -p 1234 --sort=-cpu
-
LWP和TID是一回事嗎?
是的,在Linux中LWP(輕量級(jí)進(jìn)程)和線程ID(TID)是同一個(gè)概念的不同說法。
基本上就這些。掌握好ps -L,再配合其他工具,就能輕松查看和分析Linux進(jìn)程的子線程狀態(tài)了。