suricata中的数据结构之hash表

suricata中使用了多种的数据结构,哈希表就是其中的一种。本篇文章分析一下suriata中的哈希表,在suciata的很多地方使用到了该种数据结构。同时像suricata中的哈希表的实现其实是可以直接拿来应用在具体的项目中的,因为suicata单独将哈希表的实现抽出来形成单独的文件util-hash.c。

hash table设计的初衷是为了实现快速的查询,像C语言中的数组就是一种简单的哈希表。给定一个key值(数组中称之为index),能够根据key值快速的找到对应的value(数组实现了O(1)的查询)。hash table 的key值不在仅限于整形,可以是字符串任意类型,通过hash函数,得到index,能够快速的定位到value的值,通常是远小于O(n)的查询速度。

suricata util-hash.c的实现并不复杂,如下图;
suricata中的数据结构之hash表_第1张图片
通常的hash表都包含上图的几个结构,包括hash table的初始化,增加,删除,查询,释放以及hash函数的定义。

哈希表初始化:

初始化函数HashTable* HashTableInit(uint32_t size, uint32_t (*Hash)(struct HashTable_ *, void *, uint16_t), char (*Compare)(void *, uint16_t, void *, uint16_t), void (*Free)(void *)),做两件事情:

  • 1,确定hash表的长度,不同的key值通过hash函数不可避免的产生冲突,产生的冲突key对应的value都是挂在同一个index下面,一个index下面可以包含多个hash桶(具体的value内容)。hash表的大小往往受value个数的数量影响。太小的话,每个桶下面的value过多,查询效率不高;太大的话,占用的内存过多,往往需要根据实际的情况选择合理的值。suricata中使用到哈希表的地方包括包括规则的metadata以及classtype,对应的函数调用为DetectMetadataHashInit SCClassConfInitContextAndLocalResources。由于classification文件中对应的classtype中种类较少,一共60种上下(后续新增的个数有限),因此此处的hash桶设置为128个。而meta是自定义的,种类不确定性较大,因此设置为4096,较大。
  • 2,确定一些函数的使用,包括hash函数,value值的大小比较函数,还有内存释放函数。这些函数后面还会提到。

hash函数

hash函数的目的在于将key值转化为hash桶的索引,同一个索引下面可能存在多个hash桶,即多个value值。因为不同的key值经过hash函数计算之后有可能得到相同的索引值,因此hash函数的选择也是很重要的。但是根据具体的情况,hash函数的选择还是不一样的。util-hash.c中默认的hash函数为uint32_t HashTableGenericHash(HashTable *ht, void *data, uint16_t datalen),这种自带的hash函数一般只用于测试用例中,因为在具体的场景下都自己设计了hash函数。例如meta中使用到的hash函数为StringHashFunc,classtype中使用到的hash函数为,SCClassConfClasstypeHashFunc

哈希表新增

新增函数HashTableAdd(HashTable *ht, void *data, uint16_t datalen)用于向hash表中添加具体的数据内容,即向某个索引下面添加hash桶,盛放具体的数据内容。

哈希表查询

查询函数void *HashTableLookup(HashTable *ht, void *data, uint16_t datalen)用于查询哈希表中key值对应的value是否存在,由于存在冲突,因此需要比较同一索引下面所有的哈希桶中的value,因此需要一个value的比较函数。从该函数还可以看出,这里面key 和对应的value是同一个值,如果设计成不同的值,这需要HashTableLookup的入参包含key和value。

哈希比较函数

默认的比较函数是char HashTableDefaultCompare(void *data1, uint16_t len1, void *data2, uint16_t len2),即进行内存中的值和长度进行比较,还可以看到使用的都是void类型的指针,有效的泛化输入的数据类型。meta中的比较函数为StringHashCompareFunc,实现的是同样的功能。classtype中的SCClassConfClasstypeHashCompareFunc函数则是比较指定的内容。

哈希桶删除

哈希桶删除函数为int HashTableRemove(HashTable *ht, void *data, uint16_t datalen),即释放哈希表中的某一项申请的哈希桶内存。

哈希表删除

哈希表删除函数为void HashTableFree(HashTable *ht),即释放整个哈希表的空间,包括所有的哈希桶空间,一般是哈希表不再使用,例如系统结束的时候进行调用。

void HashTableRegisterTests(void)为哈希表的测试用例。

综上,suricata定义了这些基本的数据结构,不仅方便了项目中数组的组织管理,同时util-hash.c可以单独拿出来到其他项目中进行使用,非常的有用。

本文为CSDN村中少年原创文章,未经允许不得转载,博主链接这里。

你可能感兴趣的:(suricata)