如何减少Linux上一个进程的所有线程(和子线程)?


22

Linux没有(还)遵循POSIX.1标准,它的是一renice对过程的影响“的过程中所有的系统范围线程”,因为根据并行线程(7)DOC “线程不共用一个很好的价值。”

但是,有时,renice与给定进程相关的“一切” 可能很方便(一个示例是Apache子进程及其所有线程)。所以,

  • 我怎么能renice全部线程属于给定进程?
  • 我如何才能将renice所有子进程都属于给定进程?

我正在寻找一个相当简单的解决方案。

我知道流程组有时会有所帮助,但是,它们并不总是与我想做的事情相匹配:它们可以包含更广泛或不同的流程集。

使用cgroupManaged by systemd可能也有帮助,但是即使我有兴趣了解它,我也大多在寻找“标准”解决方案。

编辑:还说man (7) pthreads:“一个进程中的所有线程都放在同一线程组中;线程组的所有成员共享相同的PID”。那么,甚至renice没有它自己的PID的东西也可能吗?

Answers:


19

您可以使用/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

man (7) pthreads关于当前(NPTL)的实现说:“一个进程中的所有线程都放在同一个线程组中;线程组的所有成员共享相同的PID”和“线程不共享相同的nice值”。那么,当renice使用PID来执行此操作时,如何放弃没有自己的PID的线程呢?
Totor

我在线程ID上尝试了renice,它报告24995 (process ID) old priority 0, new priority -10。24995没有出现在中ps,所以这不是一个过程。也许重新线程确实有效?
Stefan Reich

9

不错的价值还是CPU份额?

请注意,由于自动任务分组,尤其是在使用systemd时,如今,好的值可能在“整个系统”中不太重要。请参阅此答案以获取更多详细信息。

线程和进程之间的区别

在Linux上的一个重要问题,因为文档永久性地使人怀疑(例如,关于没有自己的PID的线程)。

注意:此答案准确解释了Linux线程。

简而言之:内核仅处理“可运行实体”,即可以运行调度的东西。在内核方面,这些实体称为流程。线程只是与另一线程共享(至少)内存空间和信号处理程序的一种进程。

每个此类进程都有一个系统范围的唯一标识符:PID(进程ID)。对于所谓的线程,有时也称为TID(线程ID),但从sysadmin(和内核!)的角度来看,TID和PID是同一件事(它们共享相同的名称空间)。

结果,您可以 renice单独使用每个“线程”,因为它们具有自己 PID 1

递归查找所有PIDrenice

我们需要获取所有待处理进程(子进程或线程组中的子进程)的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)

1请注意,为了符合POSIX,getpid(2)在线程内调用不会为您提供此可运行实体的系统范围内的唯一ID(PID),而是给您“线程组”内主进程的PID。您需要致电gettid(2)。有关更多信息,请参见此答案


6

不应将进程PID和线程ID有时写为TID或在ps命令LPW中混淆。该s命令具有显示线程的选项,并在下面tophtop您之间切换线程并按H字母进行处理。正如@Totor先前所讲的那样,对于NPTL(这是当前内核> 2.6的当前实现),所有线程都具有相同的pid,但是它们具有不同的tid。您可以通过以下方式显示进程的所有线程:

$ ps -Ljf <pid>

这些tid是之下目录的名称/proc/<pid>/task,即使renice(1)表示将其默认参数用作pid时,它也仅对主线程起作用(这是在Linux实现中的错误,如setpriority(2)所述。 )),也可以将其应用到tid并重新注册线程。这就是为什么@Anton的答案有效的原因。

但是大多数情况下,有一种更简单的方法可以达到期望的结果,所有这些线程共享相同的pgid,这是组长的pid。您可以通过发出pgid来屈服:

$ renice -g <pgid>

如果您不想放弃依赖于同一组长的其他流程,则必须使用@Anton的配方:

$ renice <priority> $(ls -1 /proc/<pid>/task)

要么:

$renice <priority> $(ps --no-header -Lo tid <pid>)

您可能还想知道同一组中除要撤消的进程之外还有哪些其他进程,也就是说,共享相同pgid的进程。您可以使用ps(1)ps不允许按组长选择进程,但是可以使用grep a ps来执行。pgid的进程1908将由以下命令给出:

$ ps --no-header axo pid,pgid |sed -n '/^ *[0-9][0-9]*  *1908/s/[0-9][0-9]* *$//p'

或者,如果您更喜欢awk进行sed:

$ ps --no-header axo pid,pgid|awk '{if ($2=="1908") print $1;}'

这似乎在4.19.4(截至目前的Debian Stretch)上无法正常工作: $ renice -n 18 -g 8524 renice: failed to get priority for 8524 (process group ID): No such process $ ps --no-header axo pid,pgid|awk '{if ($2=="8524") print $1;}' 鉴于Totor的方法仍然有效/仍然有效:$ /bin/ls /proc/8524/task | /usr/bin/xargs renice 19 2739 (process ID) old priority 19, new priority 19 2740 (process ID) old priority 19, new priority 19 ... 我已通过/ proc,htop,pstree等确认,我确实具有正确的top-级别PID。也许在过去的一年中发生了一些变化。
Bill McGonigle

我不知道你是如何进行@ bill-mcgonigle测试的,我只是在Debian Stretch上尝试了三个内核4.9.0。关于Debian测试的4.18.0和4.19.0;就像我上面说的那样。
marcz

就像我说的,Debian Stretch在4.19.4上显示了命令和输出;两者之间的差异似乎是4.19.0与4.19.4,但令我惊讶的是,这样的次要版本之间会有很大的变化。
Bill McGonigle

我猜您的进程8524是所有线程进程TID或LPW的PID,而不是进程组的PID,因此,您当然可以找到其中的所有线程,/proc/8524/task但是renice -g会失败。当您查看进程树时,一个分支位于同一进程组中,而不仅仅是一个线程进程。再试一次检查的结果ps -Ljf
marcz

0

我想建议在使用renice时使用-g(进程组)参数而不是-p(进程ID)。如果没有bash-foo,它会执行相同的操作。

(sudo) renice -n <NEW_PRIORITY> -g <MAIN_PROCESS_ID>

marcz的答案已经提到了这一点。
Totor

-1

这是我的脚本:

pgrep -v <PROCESS_NAME> | sudo xargs renice <NEW_PRIORITY>

1
这会在您命名的每个进程上启动renice。我个人认为此命令是危险且不足的。
Totor

我想知道他是否意味着-w不是-v
Diablo-D3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.