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的實現並不複雜,如下圖;
在這裏插入圖片描述
通常的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村中少年原創文章,未經允許不得轉載,博主鏈接這裏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章