为了在内核中可靠的持有一个进程,分析一下PID

解释一下struct pid:
struct pid是kernel内部用来辨别各个进程概念。每一个struct pid都对应一个独立的task、进程组、session。当有进程attach到一起,struct pid就会组成为一个hash table,如此以来struct pid索引到的进程就可以通过pid数找到。
数字到指针的索引是通过struct idr来管理,struct idr中有一个redix tree,索引是立即数,对应值是指针

一切thread以task_struct为中心,struct pid是task_struct在pid领域的代言人

在pid领域struct pid_namespace是最高集合
    pid_namespace包含struct idr idr,idr背后是一颗redix树,联系当前namespace的pid_t与struct pid指针

出现一个新的pid的时机是在创建或操作进程;
在较新的内核中,描述进程pid这个事儿由于掺杂了namespace变得复杂;
以Flag CLONE_NEWPID为界,决定在create_new_namespace时,是否创建一个新的pid_namespace
    创建新的pid第一个目标是给当前进程一个pid_namespace,第二个目标是给children用,
    如果Flage显示不必创建新的pid_namespace,
        则直接使用父进程所用struct nsproxy->struct pid_namespace pid_ns_for_children
    如果Flag显示需要创建新的pid_namespace,
        则需要alloc一个新的struct pid_namespace,同时,
            还要创建pid_namespace中为struct pid准备的slab,需要注意的是,
            struct pid的slab并不等于sizeof(struct pid),
            这与struct pid末元素struct upid个数有关,
                upid用来指向当前struct pid所有的struct pid_namespace
                这里需要解释一下:pid_namespace是可以嵌套的,不断创造子pid_namespace
                所以一个struct pid是可能属于多个pid_namespace
                也就意味着,一个struct pid可能有多个pid_t,分布在多级pid_namespace中
                struct upid的两个元素nr和struct pid_namespace *ns
                    nr就是在对应ns中的pid_t
                    ns在struct pid构建时,按照嵌套层数,指向各层struct pid_namespace
            所以这个slab的大小是
                sizeof(struct pid) + (父_pid_ns->level + 1 + 1) * sizeof(struct upid)
                多加一个1似乎是垫子
    另外需要提到的是一个namespace的主结构体struct nsproxy,这个是每个task_struct一个的namespace入口,包含所有支持命名空间的子系统fs(mount)/uts/network/sysvipc/pid(for children)/net/cgroup

问题:PIDTYPE_PID/PIDTYPE_PGID/PIDTYPE_SID这几个不同的type的处理
    pid描述一个thread
    pgid描述一个thread group leader
    sid描述一个session

    由此,task_struct中struct pid_link pids[PIDTYPE_MAX]数组分别指向
        PIDTYPE_PID-当前thread的struct pid
        PIDTYPE_PGID-当前thread的thread group leader的struct pid
        PIDTYPE_SID-当前thead所在session的struct pid

    在copy_process过程在Flag没有CLONE_THREAD(不是创建线程)的情况下,
        kernel仅保障了thead group leader(进程leader)的PIDTYPE_PGID/PIDTYPE_SID与父进程相同。
        对于非thread group leader(普通线程),未找到对PIDTYPE_PGID/PIDTYPE_SID的配置
    
问题:struct task_struct->pid_t pid中是该进程在哪个namespace的pid
    copy_process函数中可以看到,task_struct->pid = struct pid->numbers[0].nr,也就是最高层namespace
    
提示:Flag CLONE_THREAD对task_struct中的struct task_struct group_leader和pid_t tgid的影响
    对CLONE_THREAD,group_leader/tgid与current的group_leader/tgid一致
    对于非CLONE_THREAD,group_leader指向新创建的task本身,tgid即为新创建task的pid

提示:关于struct pid->unsigned int level如何指引pid_t查找task_struct
    这个level值很重要,struct pid归属与多个namespace,当一个进程根据pid_t值查找task时,
        首先要确定的是,这个pid_t属于哪个pid_namespace
        查找是task发起的,自然不应该跃出此task所属的pid_namespace,
        于是需要确定task是活跃在哪层pid_namespace,
        level就用来确定这个层级信息
        由此struct pid->struct upid[struct pid->level].struct pid_namespace
            就指向一个task活跃的pid_namespace(接口task_active_pid_ns)
    有了pid_t所在的pid_name_space,通过idr查找radix tree即可定位pid_t所指进程

遗留:没有想明白为什么struct pid不直接指向struct task_struct,
    而是将task_struct->struct pid_link pids[type]-node与struct hlist_head tasks[type]构成的链表
    链表里会有其他元素??无论会不会有其他元素,似乎只有first元素是被使用的,可能每次压first会引起
    旧有first压栈效果,然后first被取出时,旧有first还能生效???不是太理解这部分设计。
对遗留的解释:PIDTYPE_PID可能只会有一个元素(不确定),但是对于trPIDTYPE_PGID/PIDTYPE_SID肯定是可以织有多个

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值