进程组
Liunx下每个进程都隶属于一个进程组,因此它们除了PID,还有进程组ID(PGID),我们可以用如下函数来获取指定进程的PGID:
#include <unistd.h>
pid_t getpgid(pid_t pid);
该函数成功时返回进程pid所属进程组PGID,失败则返回-1并设置errno。
每个进程组都有一个首领进程,其PGID和PID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。
下面这个函数用来设置PGID:
#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid);
这个函数将PID为pid的进程的PGID设置为pgid。
- 如果pid和pgid相同,则由pid指定的进程将被设置为进程组首领
- 如果pid为0,则表示设置当前进程的PGID为pgid
- 如果pgi为0,则使用pid作为目标PGID。
setpgid调用成功时返回0,失败返回-1并设置errno。
这里需要注意的是:
一个进程只能设置自己或者其子进程的PGID。并且,当子进程调用exec系列函数后,我们也不能再在父进程中对它设置PGID。
会话
一些有关联的进程组将形成一个会话(session)。下面的函数用于创建一个会话:
#include <unistd.h>
pid_t setsid(void);
这个函数不可以由进程组的首领进程调用,否则将产生一个错误。对于非组首领的进程,调用该函数不仅创建新会话,而且有如下额外效果:
- 调用进程会成为会话的首领,此时该进程是新会话的唯一成员
- 新建一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领
- 调用进程将甩开终端(如果有的话)
该函数成功时返回新的进程组的PGID,失败则返回-1并设置errno。
Linux进程并未提供所谓会话ID(SID)的概念,但Linux系统认为它等于会话首领所在的进程组PGID,并且提供如下函数来读取SID:
#include <unistd.h>
pid_t getsid(pid_t pid);
用ps命令查看进程关系
我们在bash shell下执行ps和less命令,所以ps和less命令的父进程是bash命令,我们可以从PPID(父进程PID)一列可以看出。这三条命令创建了一个会话ID(SID是12308)和两个进程组ID(PGID分别是12308和12316)。bash命令的PID、PGID和SID都相同,很明显它既是会话的首领也是组12308的首领。ps命令则是组12316的首领,因为其PID也是12316。