显然,为了有效地支持kill(0),内核必须跟踪进程组中的进程。但该信息根本不会以任何方式暴露给用户空间。要获取该信息,必须迭代整个 procfs 树,并检查 pgid。
对于 Linux、*BSD 等都是如此。我检查的所有 *nix 系统都有这个问题。为什么要这样设计?
编辑:更改问题,以便kill(0) 示例有意义。
答案1
您可以通过过滤 的输出来列出给定组中的所有进程ps
。
ps -e -o pgid,pid | awk -v p=1234 '$1 == p {print $2}'
没有ps
直接按 PGID 过滤的选项,可能是因为它并不经常有用。
引擎盖下的内容ps
并不重要。
这不是原子的,与kill -- -1234
.但即使有一种方法可以自动列出进程组中的进程,那又有什么好处呢?当您处理该列表时,它可能不完整,或者包含已死亡且 PID 已被重用的进程。
要对进程组中的进程集执行任何有用的操作,内核必须公开执行该操作的接口,而不仅仅是列出该组成员的接口。唯一的这样的接口是向进程发送信号。
答案2
在 Linux 上的命令行中,可以使用pgrep
带有--pgroup
(或-g
) 标志的 procps-ng。
答案3
当向 PID 0(零)发送信号时,该信号将传递给与发送者属于同一进程组的所有进程。除当前进程组之外的进程组可以通过kill(-PGID)
(或kill -- -PGID
在 shell 中)发出信号,其中PGID
是进程组 ID。
PID的进程组由函数返回getpgid()
,通过 可以找到当前进程的进程组getpgrp()
。
在 shell 中,您可以使用
$ ps -opid,pgid,command
获取当前会话的 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
澄清问题后:
这目的进程组的作用是能够向其所有成员发送信号没有了解每个成员的进程 ID。
如果没有进程组概念,则必须获取系统上的所有进程,找出它们之间的关系(使用父进程 ID)并迭代相关进程,向每个进程发送信号。
内核执行此操作,但它知道并跟踪进程组,因此它永远不必迭代全部进程仅通过该组的成员向进程组发送信号。
由于进程组ID是暴露给用户,只需查询一进程必须先查找其进程组 ID,然后才能向该组中的所有进程发送信号。