OVS 中的哈希表: shash

时间:2021-09-11 10:56:49

shash出现在OVS的代码中,定义如下:

struct hmap_node {
    size_t hash;
    struct hmap_node * next;
};
struct shash_node {
    struct hmap_node node;
    char * name;
    void * data;
}
struct hmap {
    struct hmap_node ** buckets;
    struct hmap_node * one;
    size_t mask;
    size_t n;
};
struct shash {
    struct hmap map;
};
这是一个哈希表结构,hmap配合hmap_node完成哈希表的骨架,但不携带任何数据信息
shash_node是hamp_node的子类,携带数据信息。shash是hmap的子类,但不新增任何字段
OVS 中的哈希表: shash
hmap中:
bucket     指向哈希桶
one        
mask       桶的长度,用以将散列值转化为桶索引
n          哈希表中结点的总数
之所以记录mask与n,是因为hmap本身是有扩容与缩容机制的
在hmap_insert中
static inline void
hmap_insert_at(struct hmap *hmap, struct hmap_node *node, size_t hash,
               const char *where)
{
    hmap_insert_fast(hmap, node, hash);
    if (hmap->n / 2 > hmap->mask) {
        hmap_expand_at(hmap, where);
    }
}
就是通过hmap中结点数量如果大于桶位的两倍,就对桶进行扩容
one字段比较特殊,这个字段一般情况下是用不到的,只有一个场合会用到
/* Initializer for an immutable struct hmap 'HMAP' that contains 'N' nodes
 * linked together starting at 'NODE'.  The hmap only has a single chain of
 * hmap_nodes, so 'N' should be small. */
#define HMAP_CONST(HMAP, N, NODE) {                                 \
        CONST_CAST(struct hmap_node **, &(HMAP)->one), NODE, 0, N }
这种情况下,整个hmap其实退化成了一个链表,链表表头由one字段保存,而buckets指向one字段。如下图:
OVS 中的哈希表: shash
也就是说,如果你正常的把hmap当哈希表用,是用不到one这个字段的,这个字段的值会恒为NULL

body,td { font-family: Consolas; font-size: 10pt }