映射是實現(key,value)綁定的一種數據結構。也稱爲關聯數組。可以視爲由唯一key組成的集合。每個key對應這一個value。
常規的映射實現有hash表和二叉樹,以及二叉樹的變種。
差異
hash表具有相對較好的平均時間複雜度。二叉樹有着更好的最壞時間複雜度。
hash表通過hash函數能夠映射不同類型的key。二叉樹沒有hash,更多用於同類key。
hash表中的key經過hash之後是無序的,便於點查找(linkedhashmap是又加了一個指針)。二叉樹能夠滿足順序保證,便於範圍查找。
另外從內存上來說,hash表有效數據的內存佔比較小,它的收縮操作太過於浪費時間,不收縮只擴展的話,太浪費內存。
二叉樹在內存上釋放和擴展有着天然獨特的優勢。
idr
idr:是用於將uid和一個數據地址進行綁定的一種映射。文件路徑爲: include/linux/idr.h
由於uid的特殊性:組成元素在固定範圍內。相比較於尋常的二叉樹,基數樹(Redix)顯然更適合。
idr中有兩個數據結構:idr 和idr_layer
idr數據結構類似於list_head。用於管理idr整個樹的信息。其中最關鍵的是top。它指向了根節點的idr_layer。
struct idr {
struct idr_layer __rcu *hint; /* the last layer allocated from */
struct idr_layer __rcu *top; // idr的頂層(根節點)
int layers; /* only valid w/o concurrent changes */
int cur; /* current pos for cyclic allocation */
spinlock_t lock;
int id_free_cnt;
struct idr_layer *id_free;
};
idr_layer就是每個樹中每個節點的數據結構。每個節點有256個指針數組(在64位中,IDR_BITS=8),還有一個槽位圖。槽位圖是用於快速查找那些指針數組已經被使用。它是由256個bit組成。第x個指針數組被使用,那麼第x個bit就被置1。
每個指針數組指向下一層idr_layer。下一層的idr_layer也有一個指針指向它的父節點。
struct idr_layer {
int prefix; /* the ID prefix of this idr_layer */
int layer; /* 第幾層 distance from leaf */
struct idr_layer __rcu *ary[1<<IDR_BITS]; /* IDR_BITS = 8 該層有256個指針,指向256個idr_layer*/
int count; /* When zero, we can release it */
union {
/* A zero bit means "space here" */
DECLARE_BITMAP(bitmap, IDR_SIZE); /* 槽位圖 */
struct rcu_head rcu_head;
};
};
所以idr數據結構的圖示爲:(只用了兩層作爲舉例)。每層的arry的下標對應着uid的數值組成。
第一句經過arry[1]、array[2]。所以uid1,也就是映射中的key1爲0x0102,value1是一個指向My love for you,a little more than yesterday,這段文字的指針。
第二句經過arry[255]、array[0]。所以uid2,也就是映射中的key2爲0xff00,value2是一個指向a little less than tomorrow.這段文字的指針。
所以 string=&Lookup(uid1)+&Lookuo(uid2)。得到string爲
My love for you,a little more than yesterday,a little less than tomorrow。
翻譯:我對你的愛,略勝昨日,稍遜明朝~。
願大家:愛家庭,愛工作,clean code。