Linux Kernel Source - 进程哈希表浅析

哈希表实际上是一个struct task_struct * 的指针数组,即每个元素指向一组pid的进程描述符链表(此处一组不是指gid相同,而是pid满足如下第三行的宏定义,且相同)。

在Linux 2.4内核中定义如下:

#define PIDHASH_SZ (4096 >> 2)
extern struct task_struct *pidhash[PIDHASH_SZ];       //定义哈希表数组的大小为1024
#define pid_hashfn(x)    ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))   //x为进程pid,有此句可知可能存在多个进程pid对应一个哈希表元素。
哈希表如下图所示:

哈希函数并不总能确保PID与表的索引一一对应,两个不同的PID散列到相同的索引称为冲突。

既然有多个进程描述对应一个哈希表元素,那么怎样将一组进程描述符组成链表,并对应一个哈希表元素呢?

首先一下task_struct中与哈希表有关的两个字段:

struct task_struct{
        ......
	struct task_struct *pidhash_next;        //哈希链表的下一个文件描述符的地址
	struct task_struct **pidhash_pprev;      //哈希链表的上一个文件描述符指针的地址
        ......
};
将新的的进程描述符插入哈希链表的实现如下:

static inline void hash_pid(struct task_struct *p)    //p为新进程描述符指针
{
	struct task_struct **htable = &pidhash[pid_hashfn(p->pid)]; //与之对应的哈希表元素的地址,*htable指向一组进程描述符的哈希链表的首地址

	if((p->pidhash_next = *htable) != NULL) //*htable 不为空,即哈希链表不为空,将新的描述符插入链表第一的位置,其pidhash_next字段,指向原链表首部
		(*htable)->pidhash_pprev = &p->pidhash_next;//原链表首个进程描述符的pidhash_pprev初始化为,新链表首(即*p)pidhash_next成员的地址
	*htable = p;    //更新哈希表元素
	p->pidhash_pprev = htable;     //初始化新进程描述符的pidhash_pprev成员
}

从哈希链表中删除一个文件描述符:

static inline void unhash_pid(struct task_struct *p)
{
	if(p->pidhash_next)         //如果*p不是哈希链表的尾端
             p->pidhash_next->pidhash_pprev = p->pidhash_pprev; //*p下一个进程描述符的pidhash_pprev初始化为*p的pidhash_pprev
        *p->pidhash_pprev = p->pidhash_next; //*p上一个进程描述符的指针指向*p的下一个文件描述符,由以上两句把进程描述符*p从链表中独立出来,即删除。
}

根据进程pid查找进程描述符的指针:

static inline struct task_struct *find_task_by_pid(int pid)
{
	struct task_struct *p;
        struct task_struct **htable = &pidhash[pid_hashfn(pid)];  //根据pid计算哈希表元素地址,即进程描述符所在链表头结点的地址
       
        for(p = *htable; p && p->pid != pid; p = p->pidhash_next) //如果pid不等于当前哈希链表节点中的pid字段,则扫描下一个节点,直到相等
		;

	return p;      //找到返回进程描述符的指针
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值