在编写内核模块的过程中,我们经常会创建percpu的hash表,比如定义结构如下:
struct A {
int a;
int b;
struct hlist_node hlist_node;-----------------hash node,用来挂载在hash冲突链上的成员
。。。
}
然后定义一个 A[hash桶的大小],在定义一个hlish_head的数组C,用来做数组A的hlist_node的管理头,这个hash之后取相应的hash冲突链的头。一般使用如下方式初始化:
for循环:
INIT_HLIST_HEAD( C+ i);
在初始化C之后,
下面,怎么确定一个hash桶的元素已经被使用呢?常见的做法是:
1.在A的结构中维护一个标志,确定是否使用,通过遍历数组A,来找这个标志。
2.维护一个A的使用情况的链表,如freelist,里面有所有free的数组下标,这个一般和hash_head的数组放一块。
这些标准做法,在内核中都很常见,但是如果数组结构体比较大,遍历的时候,缓存被污染的概率就大了(数组结构体越大,则步长越大,访问的地址很可能就变成稀疏模型了),而此时如果数组元素个数不太多,比如只有几百上千的话,可以使用一个小技巧,
就是 find_first_zero_bit,有兴趣的同学可以 对比下,效率比前面描述的两种方法要高一些。
linux很多设计都非常精巧,多看大师的代码,取其精华,既要明白代码的原理,又要明白这些写的场景,受益匪浅。