![进程组ID是如何设置的?](https://linux22.com/image/121508/%E8%BF%9B%E7%A8%8B%E7%BB%84ID%E6%98%AF%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE%E7%9A%84%EF%BC%9F.png)
我读到会话的ID与通过系统调用创建会话的进程的pid相同setsid()
,但我没有找到任何有关如何设置进程组ID的信息。进程组ID与创建该进程组的进程的pid是否相同?
答案1
一般来说,是的,进程组 ID 等于创建进程组的进程的进程 ID,并且该进程通过将自己放入组中来创建进程组。
setpgid
您可以在系统调用及其变体的文档中找到此信息setpgrp
。 BSD 和 System V 之间的细节历史上有所不同。最常见的用例是:
- 进程将自己放入自己的进程组中,新的PGID等于PID。这可以使用 SysV
setpgrp()
或 with 来完成setpgid(0, 0)
,其中任何一个都0
可以被显式替换getpid()
。
请注意,虽然过程将自己放入组中,实际上,这通常是由启动器(shell 或守护进程监视器)在执行之前完成的程序fork
,即它是由子进程之间和execve
子进程中的启动器中的代码完成的。 进程将自身放入同一会话中的现有进程组中。 Shell 对管道执行此操作:为了在自己的进程组中运行
foo | bar
,Shell 通常会执行以下操作:- 设置管道。
- 分叉一个进程。子进程将自己放入自己的进程组中G,关闭管道的读取端并将写入端移动到 stdout,然后执行
foo
。 - 分叉一个进程。子进程将自己放入现有的进程组中G,关闭管道的写入端并将红色端移至标准输入,然后执行
bar
.
对 的调用
setpgid
可以在父进程中而不是在子进程中执行,或者除了子进程之外还可以在父进程中执行。两者都这样做可以避免出现竞争条件,以防第二个子级的初始化超过第一个子级的初始化。具有作业控制功能的 shell 通常在其自己的进程组中运行。但在退出或挂起之前,它会返回到其原始进程组(即,它将自身放回启动它的进程组,假设该组仍然存在)。
这POSIX 规范setpgid
描述了这些用例。它进一步解释了没有什么其他方法可以保证有效。特别是,虽然旧的 BSD 系统允许进程加入不同会话中的进程组或组成新的 PGID,但在大多数现代系统(包括现代 BSD)上情况并非如此。