Linux内核深度解析
上QQ阅读APP看书,第一时间看更新

2.3 进程标识符

进程有以下标识符。

(1)进程标识符:进程所属的进程号命名空间到根的每层命名空间,都会给进程分配一个标识符。

(2)线程组标识符:多个共享用户虚拟地址空间的进程组成一个线程组,线程组中的主进程称为组长,线程组标识符就是组长的进程标识符。当调用系统调用clone传入标志CLONE_THREAD以创建新进程时,新进程和当前进程属于一个线程组。

进程描述符的成员tgid存放线程组标识符,成员group_leader指向组长的进程描述符。

(3)进程组标识符:多个进程可以组成一个进程组,进程组标识符是组长的进程标识符。进程可以使用系统调用setpgid创建或者加入一个进程组。会话和进程组被设计用来支持shell作业控制,shell为执行单一命令或者管道的进程创建一个进程组。进程组简化了向进程组的所有成员发送信号的操作。

(4)会话标识符:多个进程组可以组成一个会话。当进程调用系统调用setsid的时候,创建一个新的会话,会话标识符是该进程的进程标识符。创建会话的进程是会话的首进程。

Linux是多用户操作系统,用户登录时会创建一个会话,用户启动的所有进程都属于这个会话。登录shell是会话首进程,它所使用的终端就是会话的控制终端,会话首进程通常也被称为控制进程。当用户退出登录时,所有属于这个会话的进程都将被终止。


假设某个进程属于进程号命名空间b, b的父命名空间是a, a的父命名空间是初始进程号命名空间,从b到初始的每一级命名空间分配的进程号依次是10、20和30。进程标识符数据结构如图2.3所示,进程描述符的相关成员如下。

图2.3 进程标识符数据结构

(1)成员pid存储全局进程号,即初始进程号命名空间分配的进程号30。

(2)成员pids[PIDTYPE_PID].pid指向结构体pid,存放3个命名空间分配的进程号。

(3)成员pids[PIDTYPE_PGID].pid指向进程组组长的结构体pid(限于篇幅,图2.3中没画出)。

(4)成员pids[PIDTYPE_SID].pid指向会话首进程的结构体pid(限于篇幅,图2.3中没画出)。


进程标识符结构体pid的成员如下。

(1)成员count是引用计数。

(2)成员level是进程所属的进程号命名空间的层次。

(3)数组numbers的元素个数是成员level的值加上1,3个元素依次存放初始命名空间、a和b三个命名空间分配的进程号。numbers[i].nr是进程号命名空间分配的进程号,numbers[i].ns指向进程号命名空间的结构体pid_namespace, numbers[i].pid_chain用来把进程加入进程号散列表pid_hash,根据进程号和命名空间计算散列值。