linux进程身份 - 进程标识

来源:互联网 发布:lol钻石网吧mac 编辑:程序博客网 时间:2024/06/04 18:22

1. 进程标识


在Linux中,在同一命名空间中,进程总是会被分配唯一的号码来标识它们,该号码被称作进程ID号,简称PID。对于进程和线程来说,他们都是用同样的结构体task_struct来表示,可以都被看做是进程,在内核中,他们也有自己的进程ID,也就是说会有唯一的进程ID来标识它们;但是对于线程来说,它还会有自己的线程ID,在task_struct 结构体中,用字段tgid来表示,pid代表线程所在线程组组长的PID,对于进程来说,pid和tgid是一样的。

struct task_struct {...    pid_t pid;----------进程ID    pid_t tgid;---------线程ID...}

结合线程组和进程组的知识,现在举例来介绍进程相关PID的关系,假设进程a是进程组组长,进程a用fork产生了进程b、c,然后进程c用clone产生了线程c0、c1、c2,则c、c0、c1和c2组成一个线程组,组长是c,那么他们相关的PID关系如下:

comm PID PPID PGID TGID a 3 1 1 b 10 3 1 c 11 3 1 11 c0 20 3 11 c1 21 3 11 c2 22 3 11

2. PID结构体


在linux中,有进程组、会话组这些关系,那么就得有个结构体来把相关进程都串联起来,这个结构体就是struct pid。

struct pid{    atomic_t count;    unsigned int level;-----------------------命名空间层    /* lists of tasks that use this pid */    struct hlist_head tasks[PIDTYPE_MAX];-----链表    struct rcu_head rcu;    struct upid numbers[1];-------------------对应命名空间的upid};

上述结构体有个关键的字段是tasks数组,这个数组有PIDTYPE_MAX项,分别是PID(是PIDTYPE_PID的简写,以下相同)、PGID、SID,tasks[PID]链表链接的是创建此pid结构体的进程,tasks[PGID]链接的是这个进程组中的所有进程,tasks[SID]链接的是这个会话组中的所有进程。相关关系如下图:

这里写图片描述

在上图中有前提条件是:A是一个进程组组长。如果A不是进程组组长,那么进程A的pids[PID]->pid就不会指向pid:A,而是会指向他所在的进程组组长创建的pid:X(X代表进程组组长)。

从图中可以看出进程A用fork创建了两个进程B和C,然后B和C都加入了结构体pid:A的链表tasks[PGID]中,在task_struct结构体中有一个专门的结构体字段pids来管理这些关系

struct task_struct {...    struct pid_link pids[PIDTYPE_MAX];------有三个数组...}
struct pid_link{    struct hlist_node node;----------链表节点,加入进程组和会话组的结点    struct pid *pid;-----------------pid结构体};

3. 命名空间


命名空间提供了虚拟化的一种轻量级形式,使得我们可以从不同的方面来查看运行系统的全局属性。

创建进程的时候,根据相应的命名空间,就会创建对应空间的upid,而且会分配一个唯一的数字id,在字段upid->nr中表示。假如进程所在的命名空间有3层,那么就会在每一个空间创建一个upid,并且会把这三个upid都加入全局散列表pid_hash。虽然有3个upid,但是都是对应这同一个struct pid。在最顶端的层level0,是全局层,每一个子空间层最终都会映射到此层,子空间会层层映射父空间。

struct upid {    /* Try to keep pid_chain in the same cacheline as nr for find_vpid */    int nr;----------------------------在对应空间的id号    struct pid_namespace *ns;----------所在的空间    struct hlist_node pid_chain;-------加入到全局pid_hash};

命名空间与upid的关系如下图:

这里写图片描述

0 0