如何设置进程组 ID?

use*_*202 12 process process-groups

我读到会话的 ID 与通过setsid()系统调用创建会话的进程的 pid 相同,但我没有找到有关如何设置进程组 ID 的任何信息。进程组 ID 是否与创建进程组的进程的 pid 相同?

Gil*_*il' 14

一般来说,是的,进程组 ID 等于创建进程组的进程的进程 ID——并且该进程通过将自己放入该组来创建进程组。

您可以在setpgid系统调用及其变体的文档中找到此信息setpgrp。BSD 和 System V 之间的细节历来有所不同。最常见的用例是:

  • 一个进程将自己放入自己的进程组中,新的PGID就等于PID。这可以通过 SysV 来完成,也可以setpgrp()使用setpgid(0, 0)其中任何一个0都可以用显式getpid().
    请注意,虽然进程将自己放入组中,但实际上,这通常在执行程序之前由启动器(外壳程序或守护程序监视器)完成,即由子进程之间forkexecve子进程中的启动器中的代码完成。
  • 进程将自己放入同一会话中的现有进程组中。Shell 为管道执行此操作:要foo | bar在其自己的进程组中运行,Shell 通常会执行以下操作:

    1. 设置管道。
    2. 分叉一个进程。子进程将自己置于自己的进程组G 中,关闭管道的读取端并将写入端移动到 stdout,然后执行foo
    3. 分叉一个进程。子进程将自己放入现有的进程组G 中,关闭管道的写入端并将红色端移动到标准输入,然后执行bar

    调用setpgid可以在父进程中执行,而不是在子进程中执行。如果第二个孩子的初始化超过第一个孩子的初始化,在两者中都这样做可以避免竞争条件。

  • 具有作业控制的 shell 通常在其自己的进程组中运行。但是在退出或挂起之前,它返回到它原来的进程组(即它把自己放回启动它的进程组,假设该组仍然存在)。

对POSIX规范setpgid描述了这些用例。它进一步解释说,没有多少其他东西可以保证工作。特别是,虽然旧的 BSD 系统允许进程加入不同会话中的进程组或组成新的 PGID,但大多数现代系统(包括现代 BSD)并非如此。