NotePublic/Software/System/Linux/Modules/Process/Linux_进程组.md

2.7 KiB
Raw Blame History

Linux 进程组

进程组和会话是为了支持 shell 作业控制而引入的概念。

修改进程组 ID 的接口如下:

int setpgid(pid_t pid, pid_t pgid); 

这个函数的含义是,找到进程 ID 为 pid 的进程,将其进程组 ID 修改为 pgid如果 pid 的值为 0则表示要修改调用进程的进程组 ID。该接口一般用来创建一个新的进程组。

下面三个函数接口含义一致,都是创立新的进程组,并且指定的进程会成为进程组的首进程。

如果参数 pid 和 pgid 的值不匹配,那么 setpgid 函数会将一个进程从原来所属的进程组迁移到 pgid 对应的进程组。

setpgid(0,0)
setpgid(getpid(),0)
setpgid(getpid(),getpid())

setpgid 函数有一些限制:

  1. pid 参数必须指定为调用 setpgid 函数的进程或其子进程,不能随意修改不相关进程的进程组 ID如果违反这条规则则返回 -1并置 errno 为 ESRCH。
  2. pid 参数可以指定调用进程的子进程但是子进程如果已经执行了exec函数则不能修改子进程的进程组 ID。如果违反这条规则则返回-1并置 errno 为 EACCESS。
  3. 在进程组间移动调用进程pid 指定的进程及目标进程组必须在同一个会话之内。这个比较好理解,不加入公司(会话),就无法加入公司下属的部门(进程组),否则就是部门要造反的节奏。如果违反这条规则,则返回-1并置 errno 为 EPERM。
  4. pid 指定的进程,不能是会话首进程。如果违反这条规则,则返回 -1并置 errno 为 EPERM。

有了创建进程组的接口,新创建的进程组就不必继承父进程的进程组 ID 了。

最常见的创建进程组的场景就是在 shell 中执行管道命令。

代码如下:

cmd1 | cmd2 | cmd3

下面用一个简单的命令 ps ax|grep nfsd 来说明。

ps 进程和 grep 进程都是 bash 创建的子进程,两者通过管道协同完成一项工作,它们隶属于同一个进程组,其中 ps 进程是进程组的组长。

进程组的概念并不难理解可以将人与人之间的关系做类比。一起工作的同事自然比毫不相干的路人更加亲近。shell 中协同工作的进程属于同一个进程组,就如同协同工作的人属于同一个部门一样。

引入了进程组的概念,可以更方便地管理这一组进程了。比如这项工作放弃了,不必向每个进程一一发送信号,可以直接将信号发送给进程组,进程组内的所有进程都会收到该信号。

外部参考资料

  1. 一文读懂Linux进程、进程组、会话、僵尸