4.    5.1哈希表

哈希表是进行快速查找的一种有效的组织方式。Linu在进程中引入的哈希表叫做pidhash,在include/linux/sched.h中定义如下:

 

#define PIDHASH_SZ (4096 >> 2)

extern struct task_struct *pidhash[PIDHASH_SZ];

 

#define pid_hashfn(x)   ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))

 

其中,PIDHASH_SZ为表中元素的个数,表中的元素是指向task_struct结构的指针。pid_hashfn为哈希函数,把进程PID转换为表的索引。通过这个函数,可以把进程PID均匀地散列在它们的域(0 PID_MAX-1)中。

   在数据结构课程中我们已经了解到,哈希函数并不总能确保PID与表的索引一一对应,两个不同的PID散列到相同的索引称为冲突。


   Linux利用链地址法来处理冲突的PID:也就是说,每一表项是由冲突的PID组成的双向链表,这种链表是由task_struct 结构中的pidhash_next pidhash_pprev域实现的,同一链表中pid的大小由小到大排列。如图4.3所示。

 

          

         4.3  链地址法处理冲突时的哈希表

   在哈希表pidhash插入和删除一个进程时可以调用hash_ pid(  ) unhash_ pid(  )函数。对于一个给定的pid,可以通过find_task_by_pid()函数快速地找到对应的进程:

 

static inline struct task_struct *find_task_by_pid(int pid)

{

        struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];

        for(p = *htable; p && p->pid != pid; p = p->pidhash_next)

                ;

        return p;

}