Linux

如何在 Linux 上修改一個程序的所有執行緒(和子程序)?

  • February 1, 2022

Linux(尚未)遵循 POSIX.1 標準,該標准說程序renice上的 a 會影響“程序中的所有系統範圍執行緒”,因為根據pthreads(7) 文件“執行緒不共享一個共同的好值”。

但是,有時,與給定程序相關的“一切”可能會很方便renice(一個例子是 Apache 子程序及其所有執行緒)。所以,

  • 我怎樣才能屬於給定程序的renice所有執行緒?
  • 我怎樣才能屬於給定程序的renice所有子程序?

我正在尋找一個相當簡單的解決方案。

我知道流程組有時會有所幫助,但是,它們並不總是符合我想要做的:它們可以包含更廣泛或不同的流程集。

使用cgroupmanaged bysystemd也可能會有所幫助,但即使我有興趣了解它,我主要還是在尋找“標準”解決方案。

編輯:另外,man (7) pthreads說“一個程序中的所有執行緒都放在同一個執行緒組中;執行緒組的所有成員共享相同的 PID”。那麼,是否有可能renice沒有自己的PID?

遞歸查找所有 PIDrenice

我們需要獲取待處理程序的後代(子程序或執行緒組中)的所有程序(“正常”或“執行緒”)的 PI​​D。這應該是遞歸的(考慮孩子的孩子)。

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

引用自:https://unix.stackexchange.com/questions/294299