进程间关系
进程组
Linux下每个进程都隶属于一个进程组,因此它们除了PID信息外,还有进程组ID(PGID
)。我们可以用如下函数来获取指定进程PGID
:
#include <sys/types.h>
#include <unistd.h>
pid_t getpgid(pid_t pid);
该函数成功时返回进程pid所属进程组的PGID
,失败则返回-1并设置errno
。
每个进程组都有一个首领进程,其PGID
和PID
相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。下面的函数用于设置PGID
:
int setpgid(pid_t pid, pid_t pgid);
该函数将PID
为pid
的进程的PGID
设置为pgid
。
如果pid
和 pgid
相同,则由pid
指定的进程将被设置为进程组首领;
如果pid
为0,则表示设置当前进程的PGID
为pgid
;
如果pgid
为0,则使用pid
作为目标PGID
。
setpgid
函数成功时返回0,失败则返回-1并设置errno
.
一个进程只能设置自己或者其子进程的PGID
。并且,当子进程调用exec
系列函数后,我们也不能再在父进程中对它设置PGID
。
会话
一些有关联的进程组将形成一个会话(session)。下面的函数用于创建一个会话:
#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
该进程不能由进程组的首领进程进行调用,会报错。
对于非进程组首领的进程,调用该函数不仅创建新会话,还会:
- 调用进程成为会话的首领,此时该进程是新会话的唯一成员。
- 新建一个进程组,其
PGID
就是调用进程的PID
,调用进程成为该组的首领。 - 调用进程将失去终端
该函数成功时返回新的进程组的PGID
,失败则返回-1并设置errno
。
Linux进程并未提供所谓会话ID (SID)的概念,但Linux系统认为它等于会话首领所在的进程组的PGID,并提供了如下函数来读取SID
:
#include <sys/types.h>
#include <unistd.h>
pid_t getsid(pid_t pid);
使用ps命令查看进程之间的关系
在终端输入
ps -o pid,ppid,pgid,sid,comm | less
它们之间的关系如下图
从单独的进程角度看,zsh是ps和less的父进程
从组的角度看,zsh是一个组(组里面只有zsh,所以zsh是进程组首领),ps和less是一个组(ps是进程组首领)
从会话的角度看,会话里面有两个关联的进程组,其实zsh是会话的首领