一、进程ID号
UNIX进程会分配一个号码用于在其命名空间中唯一地标识它们。该号码被称作进程ID号,简称PID。用fork或clone产生的每个进程都由内核自动地分配了一个新的唯一的PID值。
1、进程ID
但每个进程除了PID之外,还有其他的ID。有下列几种可能的类型。
1)处于某个线程组中的所有进程都有统一的线程组ID。如果进程没有使用线程,则其PID和TGID相同。
线程组中的主进程被称作组长。通过clone创建的所有线程的task_struct的group_leader成员,会指向组长的task_struct实例。
2)独立进程可以合并成进程组(使用setpgrp系统调用)。进程组成员的task_struct的pgrp属性值都是相同的,即进程组组长的PID。进程组简化了向组的所有成员发送信号的操作,这对于各种系统程序设计应用是有用的。注意:用管道连接的进程包含在同一个进程组中。
3)几个进程组可以合并成一个会话。会话中的所有进程都有同样的会话ID,保存在task_struct的session成员中。SID可以使用setsid系统调用设置。
命名空间增加了PID管理的复杂性。PID命名空间按层次组织。在建立一个新的命名空间时,该命名空间中的所有PID对父命名空间都可见,但子命名空间无法看到父命名空间的PID。但这意味着某些进程具有多个PID,凡可以看到该进程的命名空间,都会为其分配一个PID。这必须反映在数据结构中。必须区分局部ID和全局ID。
1)全局ID是在内核本身和初始命名空间中的唯一ID号,在系统启动期间开始的 init 进程属于初始命名空间。对每个ID类型,都有一个给定的全局ID,保证在整个系统中是唯一的。
2)局部ID属于某个特定的命名空间,不具备全局有效性。对每个ID类型,它们在所属的命名空间内部有效,但类型相同、值也相同的ID可能出现在不同的命名空间中。
全局PID和TGID直接保存在 task_struct 中,分别是 task_struct 的 pid 和 tgid 成员:
<linux/sched.h>
这两项都是pid_t类型,该类型定义为__kernel_pid_t,后者由各个体系结构分别定义。通常定义为int,即可以同时使用2 ^ 32个不同的ID。
会话和进程组ID保存在signal_struct结构中。
<linux/sched.h>
set_task_session和set_task_pgrp用于修改会话和进程组ID。
2、管理PID
除了这两个字段之外,内核还需要找一个办法来管理所有命名空间内部的局部量,以及其他ID(如TID和SID)。这需要几个相互连接的数据结构,以及许多辅助函数。
1