如何在 Linux 上修改一個程序的所有執行緒(和子程序)?
Linux(尚未)遵循 POSIX.1 標準,該標准說程序
renice
上的 a 會影響“程序中的所有系統範圍執行緒”,因為根據pthreads(7) 文件“執行緒不共享一個共同的好值”。但是,有時,與給定程序相關的“一切”可能會很方便
renice
(一個例子是 Apache 子程序及其所有執行緒)。所以,
- 我怎樣才能屬於給定程序的
renice
所有執行緒?- 我怎樣才能屬於給定程序的
renice
所有子程序?我正在尋找一個相當簡單的解決方案。
我知道流程組有時會有所幫助,但是,它們並不總是符合我想要做的:它們可以包含更廣泛或不同的流程集。
使用
cgroup
managed bysystemd
也可能會有所幫助,但即使我有興趣了解它,我主要還是在尋找“標準”解決方案。編輯:另外,
man (7) pthreads
說“一個程序中的所有執行緒都放在同一個執行緒組中;執行緒組的所有成員共享相同的 PID”。那麼,是否有可能renice
沒有自己的PID?
遞歸查找所有 PID
renice
我們需要獲取待處理程序的後代(子程序或執行緒組中)的所有程序(“正常”或“執行緒”)的 PID。這應該是遞歸的(考慮孩子的孩子)。
Anton Leontiev的回答給出了這樣做的提示:所有文件夾名稱
/proc/$PID/task/
都是執行緒的 PID,其中包含children
列出潛在子程序的文件。然而,它缺乏遞歸性,所以這裡有一個快速而骯髒的 shell 腳本來找到它們:
#!/bin/sh [ "$#" -eq 1 -a -d "/proc/$1/task" ] || exit 1 PID_LIST= findpids() { for pid in /proc/$1/task/* ; do pid="$(basename "$pid")" PID_LIST="$PID_LIST$pid " for cpid in $(cat /proc/$1/task/$pid/children) ; do findpids $cpid done done } findpids $1 echo $PID_LIST
如果程序 PID 1234 是您想要遞歸處理的程序,現在您可以執行以下操作:
renice -n 15 -p $(/path/to/findchildren.sh 1234)
旁注
不錯的價值還是 CPU 份額?
請注意,如今,由於自動任務分組,nice 值可能在“系統範圍內”並不那麼相關,尤其是在使用systemd時。有關更多詳細資訊,請參閱此答案。
執行緒和程序的區別
注意:這個答案準確地解釋了 Linux 執行緒。
簡而言之:核心只處理“可執行實體”,即可以執行和調度的東西。在核心方面,這些實體稱為程序。執行緒只是一種與另一個共享(至少)記憶體空間和信號處理程序的程序。每個這樣的程序都有一個系統範圍的唯一標識符:PID(程序 ID)。
結果,您可以
renice
單獨“執行緒”每個“執行緒”,因為它們確實有自己的PID 1。1有關 PID (ProcessID) 和 TID 差異 (ThreadID) 的更多資訊,請參閱此答案。
您可以使用
/proc/$PID/task
查找給定程序的所有執行緒,因此您可以使用$ ls /proc/$PID/task | xargs renice $PRIO
屬於給定程序的
renice
所有執行緒。
/proc/$PID/task/$PID/children
可以使用相同的方式查找所有子程序(或者/proc/$PID/task/*/children
如果您想要給定程序的所有執行緒的所有**子程序)。$ cat /proc/$PID/task/$PID/children | xargs renice $PRIO $ cat /proc/$PID/task/*/children | xargs renice $PRIO