linux 記憶體管理 紅黑樹(未讀)

2021-06-22 20:26:30 字數 2502 閱讀 3800

2009-12-11 10:02 佚名 51cto 

字型大小:t

|  t

很多的人都開始學習linux作業系統。當我們學習linux時,會遇到很多的問題。最近看linux記憶體管理,看到紅黑樹這一部分甚為頭大,於是了解了一下紅黑樹的基本知識。詳細講解一下linux記憶體管理。

ad:wot2014:使用者標籤系統與使用者資料化運營培訓專場

很多的人都開始學習linux作業系統。當我們學習linux時,會遇到很多的問題。最近看linux記憶體管理,看到紅黑樹這一部分甚為頭大,於是了解了一下紅黑數的基本知識。詳細講解一下linux記憶體管理。

紅黑樹是平衡二叉樹的一種,它有很好的性質,樹中的結點都是有序的,而且因為它本身就是平衡的,所以查詢也不會出現非常惡劣的情況,基於二叉樹的操作的時間複雜度是o(log(n))。linux核心在管理vm_area_struct時就是採用了紅黑樹來維護記憶體塊的。

先到include/linux/rbtree.h中看一下紅黑樹的一些定義,如下:

struct rb_node  

__attribute__((aligned(sizeof(long)))); 

struct rb_root只是struct rb_node*的乙個包裝,這樣做的好處是看起來不用傳遞二級指標了。不錯,很簡單。

測試顏色和設定顏色也是水到渠成的事了。需要特別指出的是下面的乙個內聯函式:

static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, struct rb_node ** rb_link);

它把parent設為node的父結點,並且讓rb_link指向node。

我們把重點集中在lib/rbtree.c上,看看一些和紅黑樹相關的重要演算法。開始之前我們一起回憶一下紅黑樹的規則:

1. 每個結點要麼是紅色要麼是黑色;

2. 根結點必須是黑色;

3. 紅結點如果有孩子,其孩子必須都是黑色;

4. 從根結點到葉子的每條路徑必須包含相同數目的黑結點。

5、每個樹節點n的左孩子樹上的所有元素都是排在n之前,右孩子樹子上的所有元素都是排在n之後

這四條規則可以限制一棵排序樹是平衡的。

__rb_rotate_left是把以root為根的樹中的node結點進行左旋,__rb_rotate_right是進行右旋。這兩個函式是為後面的插入和刪除服務,而不是為外部提供介面。

新插入的結點都設為葉子,染成紅色,插入後如果破壞了上述規則,通過調整顏色和旋轉可以恢復,二叉樹又重新平衡。插入操作的介面函式是

void rb_insert_color(struct rb_node *node, struct rb_root *root);

它把已確定父結點的node結點融入到以root為根的紅黑樹中,具體演算法的分析可以參考[1]中第14.3節,這裡的實現和書中的講解幾乎完全一樣。怎麼確定node的父結點應該在呼叫rb_insert_color之前通過手工迭帶完成。值得指出的一點是,雖然插入操作需要乙個迴圈迭代,但是總的旋轉次數不會超過兩次!所以效率還是很樂觀的。

刪除操作多多少少都有點麻煩,它要先執行像普通二叉查詢樹的「刪除」,然後根據刪除結點的顏色來判斷是否執行進一步的操作。刪除的介面是:

void rb_erase(struct rb_node *node, struct rb_root *root);

其實它並沒有真正刪除node,而只是讓它和以root為根的樹脫離關係,最後它還要判斷是否呼叫__rb_erase_color來調整。具體演算法的講解看參考[1]中第13.3和14.4節,__rb_erase_color對應書中的rb-delete-fixup,此處的實現和書上也基本上一致。

其餘的幾個介面就比較簡單了。

struct rb_node *rb_first(struct rb_root *root);

在以root為根的樹中找出並返回最小的那個結點,只要從根結點一直向左走就是了。

struct rb_node *rb_last(struct rb_root *root);

是找出並返回最大的那個,一直向右走。

struct rb_node *rb_next(struct rb_node *node);

返回node在樹中的後繼,這個稍微複雜一點。如果node的右孩子不為空,它只要返回node的右子樹中最小的結點即可;如果為空,它要向上查詢,找到迭帶結點是其父親的左孩子的結點,返回父結點。如果一直上述到了根結點,返回null。

struct rb_node *rb_prev(struct rb_node *node);

返回node的前驅,和rb_next中的操作對稱。

void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root);

用new替換以root為根的樹中的victim結點。

因為紅黑樹的這些良好性質和實現中介面的簡易性,它被廣泛應用到核心程式設計中,大大提高了核心的效率。

通過本文的介紹你就能熟練掌握linux記憶體管理。

記憶體管理之紅黑樹

紅黑樹是平衡二叉樹的一種,它有很好的性質,樹中的結點都是有序的,而且因為它本身就是平衡的,所以查詢也不會出現非常惡劣的情況,基於二叉樹的操作的時間複雜度是o log n linux核心在管理vm area struct時就是採用了紅黑樹來維護記憶體塊的。先到include linux rbtree....

紅黑樹的管理

3.2 刪除 4 1 紅黑樹是一種自平衡二叉樹,擁有以下性質 每個節點非黑即紅 每個葉子為黑 若某節點為紅,其兩子節點均為黑 從任一節點到其葉子的所有路徑都包含相同數量的黑節點 根節點總為黑 當樹被修改 節點增 刪 時,樹會自動調整以維持上述性質的有效性。2 3紅黑樹的操作主要是插入資料和刪除資料,...

linux紅黑樹實現

linux核心紅黑樹的演算法都定義在linux 2.6.38.8 include linux rbtree.h和linux 2.6.38.8 lib rbtree.c兩個檔案中。1 結構體 cpp view plain copy print?struct rb node attribute alig...