一、进程组
1. 进程组概述
进程组是一个或多个进程的集合。
进程组随进程组首进程创建,进程组的PGID为首进程ID。进程组的生命周期从首进程的创建开始,到进程组内的最后一个进程结束或离开而结束。
2. 进程组API
(1)获取本进程进程组ID,该函数一定能够成功返回。
#include <unistd.h>
pid_t getpgrp(void);
功能:获取本进程进程组ID
参数:void
返回值:本进程进程组ID
(2)获取指定进程的进程组ID。
#include <unistd.h>
pid_t getpgid(pid_t pid);
功能:获取指定进程进程组ID
参数:进程id
返回值:
当pid==0时,作用和getpgrp();相同
当pid!=1时,成功返回进程组ID,失败返回-1
(3)设置指定进程的进程组PGID。
#include <unistd.h>
int setpgrp(pid_t pid, pid_t pgid);
功能:修改指定进程进程组ID
参数:
pid:进程pid
pgid:进程组PGID
返回值:
成功返回0,失败返回-1
二、会话
1.会话概述
会话是一个或多个进程组的集合。
会话组的创建是随着会话首进程的创建而创建的,会话的SID为首进程的ID。
一个会话中的所有进程共享单个控制终端
,控制终端会在会话首进程首次打开一个终端设备时创建。
在任意时刻,会话中的某个进程组会成为前台进程组,其他程序成为后台进程组。只有前台进程组能够从控制终端读取输入:普通的字符输入或信号终端字符。
当用户在控制终端中输入其中一个信号生成终端字符之后,该信号会被发送到前台进程组中的所有成员。`当到控制终端的连接建立起来(即打开)之后,会话首进程会成为该终端的控制进程。
会话和进程组的主要用途是用于 shell 作业控制。
终端、进程组、会话之间的关系如下图:
2.会话API
(1) 获取进程所属的会话ID
#include <unistd.h>
pid_t getsid(pid_t pid);
功能:获取进程所属的会话ID
参数:
pid:进程号,pid为0表示查看当前进程session ID。如果pid为0,会返回调 用进程的会话ID
返回值:
成功:返回调用进程的会话ID
失败:-1
(2)设置会话ID
#include <unistd.h>
pid_t setsid(void);
功能:
创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID。
参数:无
返回值:
成功:返回调用进程的会话ID
失败:-1
setsid()按照下列步骤创建一个新会话
:
- 调用进程成为新会话的首进程和该会话中新进程组的首进程。调用进程的进程组 ID和会话 ID 会被设置成该进程的进程 ID。
- 调用进程没有控制终端。所有之前到控制终端的连接都会被断开。
如果调用进程是一个进程组首进程,那么 setsid()调用会报出 EPERM 错误。避免这个错误发生的最简单的方式是执行一个 fork()并让父进程终止以及让子进程调用 setsid()。
由于子进程会继承其父进程的进程组 ID 并接收属于自己的唯一的进程 ID,因此它无法成为进程组首进程。