Linux Kernel Source - 进程双向循环链表

来源:互联网 发布:解析域名 英文 编辑:程序博客网 时间:2024/06/06 01:57

哈希表的主要作用是根据进程的pid可以快速地找到对应的进程,但它没有反映进程创建的顺序,也无法反映进程之间的亲属关系,因此引入进程双向循环链表。

union task_union {
    struct task_struct task;
    unsigned long stack[INIT_TASK_SIZE/sizeof(long)];
};

#define init_task    (init_task_union.task)                                                                //声明init_task

union task_union init_task_union = { INIT_TASK(init_task_union.task) };        // 初始化init_task_union


struct task_struct init_task,它对应的是进程0(pid为0),也就是所谓的空进程,它是所有进程的祖先。

宏SET_LINK用来向该双循环链表中插入一个进程描述符*p,插入位置在*init_task.prev_task和init_task之间,即双向循环链表的尾端,插入后*p的父进程为创建其的进程,兄进程为插入前的tail,插入后*p作为tail,即链表的尾端,这刚好吻合创建时间顺序:


#define SET_LINKS(p) do { \
    (p)->next_task = &init_task; \
    (p)->prev_task = init_task.prev_task; \
    init_task.prev_task->next_task = (p); \
    init_task.prev_task = (p); \                                               //前四句进行插入操作
    (p)->p_ysptr = NULL; \                                                     //指向弟进程的指针初始化为NULL.
    if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \    //插入后p的兄进程初始化为插入前父进程的tail子进程
        (p)->p_osptr->p_ysptr = p; \                                       //插入前父进程的tail子进程的弟进程为插入进程p
    (p)->p_pptr->p_cptr = p; \                                                //父进程的描述符的p_cptr记录最后插入的子进程地址

    } while (0)


由此我们可以看到struct task_struct的如下字段的含义:
p_pptr(Parent),父进程,记录当前进程的父进程是谁。
p_cptr(Child),子进程,记录当前进程的最后一个子进程是谁。
p_ysptr(Younger sibling), 弟进程,记录当前进程的弟进程是谁,如果当前进程是其父进程的最后一个子进程,则其为NULL,即当前进程没有弟弟。
p_osptr(Older sibling),兄进程,记录当前进程的兄进程是谁,一般指向插入前*init_task->prev_task。
原创粉丝点击