为什么没有简单的方法列出给定进程组中的所有进程?

ysh*_*hui 9 process process-management

显然,为了有效地支持 kill(0),内核必须跟踪进程组中的进程。但是该信息根本不会以任何方式暴露给用户空间。要获得该信息,必须遍历整个 procfs 树,并检查 pgid。

这适用于 Linux、*BSD 等。我检查过的所有 *nix 系统都有这个问题。他们为什么这样设计?

编辑:更改问题,使 kill(0) 示例有意义。

Gil*_*il' 7

您可以通过过滤 的输出来列出给定组中的所有进程ps

ps -e -o pgid,pid | awk -v p=1234 '$1 == p {print $2}'
Run Code Online (Sandbox Code Playgroud)

没有ps直接按 PGID 过滤的选项,可能是因为它不是很常用。

ps在引擎盖下做什么并不重要。

kill -- -1234. 但即使有一种方法可以原子地列出进程组中的进程,那又有什么好处呢?当您处理该列表时,它可能不完整或包含已死且其 PID 已被重用的进程。

为了对进程组中的一组进程做任何有用的事情,内核必须公开一个执行操作的接口,而不仅仅是一个列出组成员的接口。唯一的此类接口是向进程发送信号。


mat*_*tdm 7

从 Linux 上的命令行,可以使用pgrepfrom procps-ng 和--pgroup(or -g) 标志。


Kus*_*nda 4

当向 PID 0(零)发送信号时,该信号将传递给与发送者属于同一进程组的所有进程。除当前进程组之外的进程组可以通过kill(-PGID)(或kill -- -PGID在 shell 中)发出信号,其中PGID是进程组 ID。

PID的进程组由getpgid()函数返回,通过 可以找到当前进程的进程组getpgrp()

在 shell 中,您可以使用

$ ps -opid,pgid,command
Run Code Online (Sandbox Code Playgroud)

获取当前会话的 PID、PGID(进程组 ID)和命令行。

这可能会返回类似的内容

  PID  PGID COMMAND
20716 20716 -ksh93 (ksh93)
83662 83662 -ksh93 (ksh93)
 4322  4322 /usr/X11R6/bin/xclock
 5374  5374 tmux: client (/tmp/tmux-11000/default) (tmux)
78747 78747 -ksh93 (ksh93)
29298 29298 ps -opid
63563 63563 -ksh93 (ksh93)
63327 63327 mutt
21790 21790 -ksh93 (ksh93)
64493 64493 /bin/sh /usr/X11R6/bin/startx
14485 64493 xinit /home/kk/.xinitrc -- /usr/X11R6/bin/X :0 -auth /home/kk/.serverauth.E3cwuT5FZR
93531 93531 sh /home/kk/.xinitrc
48598 93531 flwm
28154 93531 xterm
73053 93531 xterm
Run Code Online (Sandbox Code Playgroud)

澄清问题后:

进程组的目的是能够在不知道每个成员的进程 ID 的情况下向其所有成员发送信号

如果没有进程组概念,则必须获取系统上的所有进程,找出它们之间的关系(使用父进程 ID)并迭代相关进程,向每个进程发送信号。

内核执行此操作,但它知道并跟踪进程组,因此它永远不必遍历所有进程来向进程组发送信号,而只需遍历该组的成员。

由于进程组 ID向用户公开,因此只需向一个进程查询其进程组 ID,然后就能向该组中的所有进程发送信号。

  • @yshui 我已经更新了我的答案。了解您想要解决的具体问题也很有趣。 (2认同)