struct pid
{
atomic_t count;
unsigned int level;
struct hlist_head tasks[PIDTYPE_MAX];
struct rcu_head rcu;
struct upid numbers[1];
};
虽然其名字是pid,不过实际上这个数据结构抽象了不仅仅是一个thread ID或者process ID,实际上还包括了进程组ID和session ID。由于多个task struct会共享pid(例如一个session中的所有的task struct都会指向同一个表示该session ID的struct pid数据对象),因此存在count这样的成员也就不奇怪了,表示该数据对象的引用计数。
在了解了pid namespace hierarchy之后,level成员也不难理解,任何一个系统分配的PID都是隶属于某一个namespace的,而这个namespace又是位于整个pid namespace hierarchy的某个层次上,pid->level指明了该PID所属的namespace的level。由于pid对其parent pid namespace也是可见的,因此,这个level值其实也就表示了这个pid对象在多少个pid namespace中可见。
在多少个pid namespace中可见,就会有多少个(pid namespace,pid number)对,numbers就是这样的一个数组,表示了在各个level上的pid number。tasks成员和使用该struct pid的task们关联,我们在下一节描述。
3、进程描述符中如何体现tid、pid、sid、pgid?
由于多个task共享ID(泛指上面说的四种ID),因此在设计数据结构的时候我们要考虑两种情况:
(1)从task struct快速找到对应的struct pid
(2)从struct pid能够遍历所有使用该pid的task
在这样的要求下,我们设计了一个辅助数据结构:
struct pid_link
{
struct hlist_node node;
struct pid *pid;
};
其中node是将task串接到struct pid的task struct链表中的节点,而pid指向具体的struct pid。这时候,我们可以在task struct中嵌入一个pid_link的数组:
struct task_struct {
……
struct pid_link pids[PIDTYPE_MAX];
……
}
Task struct中的pids成员是一个数组,分别表示该task的tid(pid)、pgid和sid。我们定义pid的类型如下:

enum pid_type
{
PIDTYPE_PID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX
};
一直以来我们都是说四种type,tid、pid、sid、pgid,为何这里少定义一种呢?其实开始版本的内核的确是定义了四种type的pid,但是后来为了节省内存,tid和pid合二为一了。OK,现在已经引入太多的数据结构,下面我们用一幅图片来描述数据结构之间的关系:

对于一个进程中的多个线程而言,每一个线程都可以通过task->pids[PIDTYPE_PID].pid找到该线程对应的表示thread ID的那个struct pid数据对象。当然,任何一个线程都有其所属的进程,也就是有表示其process id的那个struct pid数据对象。如何找到它呢?这需要一个桥梁,也就是task struct中定义的thread group 成员(task->group_leader),通过该指针,一个线程总是很容易的找到其对应的线程组leader,而线程组leader对应的pid就是该线程的process ID。因此,对于一个线程,其task->group_leader->pids[PIDTYPE_PID].pid就指向了表示其process id的那个struct pid数据对象。当然,对于线程组leader,其thread ID和process ID的struct pid数据对象是一个实体,对于非线程组leader的那些普通线程,其thread ID和process ID的struct pid数据对象指向不同的实体。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76987-3.html
怎么感觉美佬象个小孩