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

51 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Linux 进程组
进程组和会话是为了支持 shell 作业控制而引入的概念。
修改进程组 ID 的接口如下:
```cpp
int setpgid(pid_t pid, pid_t pgid);
```
这个函数的含义是,找到进程 ID 为 pid 的进程,将其进程组 ID 修改为 pgid如果 pid 的值为 0则表示要修改调用进程的进程组 ID。该接口一般用来创建一个新的进程组。
下面三个函数接口含义一致,都是创立新的进程组,并且指定的进程会成为进程组的首进程。
如果参数 pid 和 pgid 的值不匹配,那么 setpgid 函数会将一个进程从原来所属的进程组迁移到 pgid 对应的进程组。
```cpp
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 中执行管道命令。
代码如下:
```bash
cmd1 | cmd2 | cmd3
```
下面用一个简单的命令 ps ax|grep nfsd 来说明。
ps 进程和 grep 进程都是 bash 创建的子进程,两者通过管道协同完成一项工作,它们隶属于同一个进程组,其中 ps 进程是进程组的组长。
进程组的概念并不难理解可以将人与人之间的关系做类比。一起工作的同事自然比毫不相干的路人更加亲近。shell 中协同工作的进程属于同一个进程组,就如同协同工作的人属于同一个部门一样。
引入了进程组的概念,可以更方便地管理这一组进程了。比如这项工作放弃了,不必向每个进程一一发送信号,可以直接将信号发送给进程组,进程组内的所有进程都会收到该信号。
## 外部参考资料
1. [一文读懂Linux进程、进程组、会话、僵尸](https://blog.csdn.net/21cnbao/article/details/104489577)