linux内核hash表的使用

Linux内核中最常用的两种表

一种为lish,一种双向链表

一种为hlist,一种哈希链表

本文从代码和实际运用角度上解释以下内核如何使用哈希链表


先上哈希list的结构

linux内核hash表的使用_第1张图片


先从应用的角度上观察hash链表

内核查找进程控制块是通过hash链表的方法查找的

linux内核hash表的使用_第2张图片

内核申请了一片空间来存储hash_list

hlist的个数为pidhash_size(具体体系结构不一样,算法也很复杂,直接在内核中printk打印出来就好了)

对每个节点进行初始化 将next 和 pprev置为NULL

linux内核hash表的使用_第3张图片

这里我节选了alloc_pid函数中将根据upid的nr和ns将pid_chain插入到指定的hash_hlist中,显然这里的hash算法是pid_hashfn

具体hashfn是如何计算这里暂不分析,这是个纯数学的东西,我要搞懂的是内核的hlist原理

linux内核hash表的使用_第4张图片

内核如何去寻找pid的

根据nr和ns,利用pid_hashfn算法,快速定位找到自己所在的hash_list

然后遍历这个hash_list,匹配nr 和 ns,找到自己的pid

linux内核hash表的使用_第5张图片

至于pprev是指向前节点的next指针

通过修改pprev在头部插入新节点的时候,能修改头部的指针,具体参考上图的最后一句

为什么不用双向链表,而只用first来做单向链表,是因为在hash链表中,hashlist的数量很大,在初始化过程中就占用了内存空见,为了节约空间将hashlist做为单向链表


冲突解决办法

内核利用pid的nr和ns来将所有关键字相同的pid连在一起来解决hash冲突

通过hashfn算法计算出nr和ns关键字所在的hashlist,如果这个hashlist有多个pid就进行遍历,找到nr和ns相等的pid

为什么呢,因为hashfn 可能因为不同的nr和ns计算出相同的散列地址,进而把nr和ns不同的pid放入一个hashlist


总结:

绝大多数情况下,一个hashlist就只有一个pid

冲突的情况下,一个hashlist有多个pid,再进行遍历,比较nr和ns,找出我们需要的那个

在不冲突的情况下,查找pid的效率是O(1),冲突的情况下是O(n),主要看hashfn这个算法



你可能感兴趣的:(linux内核hash表的使用)