亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
123下一頁
最近訪問板塊 發(fā)新帖
查看: 14803 | 回復: 26
打印 上一主題 下一主題

linux內(nèi)核priority search tree詳解--->王者歸來,先發(fā)一篇狠的 [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-04-24 00:44 |只看該作者 |倒序瀏覽
本帖最后由 cluter 于 2011-04-24 00:49 編輯

忙了好久,總有有時間看內(nèi)核,最近研究下了LINUX內(nèi)核“頁面回收”時候采用的PST樹算法。
            
           PST是 radix tree和heap tree的綜合體。而且LINUX的實現(xiàn)和傳統(tǒng)的算法還不一樣,甚是花了不少時間啊。廢話少說了,先上圖。



下面是插入操作:還是先上圖再帖代碼





struct prio_tree_node *prio_tree_insert(struct prio_tree_root *root,struct prio_tree_node *node)
{
                獲取insert_node的radix和heap
        get_index(root, node, &radix_index, &heap_index);
               
                1 如果樹是空
           2 要insert_node的heap大于root的maxindex,則要先"擴展"樹
        if (prio_tree_empty(root) ||heap_index > prio_tree_maxindex(root->index_bits))
                return prio_tree_expand(root, node, heap_index);
               
                從root節(jié)點開始比較
        cur = root->prio_tree_node;
                獲取mask掩碼
        mask = 1UL << (root->index_bits - 1);

        while (mask) {
                                獲取cur_node的radix和heap
                get_index(root, cur, &r_index, &h_index);
                                
                                如果insert_node已經(jīng)存在,則直接返回當前node
                if (r_index == radix_index && h_index == heap_index)
                        return cur;
                                
                                1 cur_node->heap < insert_node->heap
                                2 cur_node->heap == insert_node->heap&&cur_node->radix > insert_node->radix,則交互兩個節(jié)點
                                if (h_index < heap_index ||(h_index == heap_index && r_index > radix_index))
                                {
                        struct prio_tree_node *tmp = node;
                                                
                                                交換insert_node和cur_node
                        注意:insert_node已經(jīng)變成cur_node
                                                node = prio_tree_replace(root, cur, node);
                                                
                                                讓cur指針指向已經(jīng)插入的node節(jié)點
                        cur = tmp;
                                                
                        /* 交換radix和heap的值*/
                        index = r_index;
                        r_index = radix_index;
                        radix_index = index;
                        index = h_index;
                        h_index = heap_index;
                        heap_index = index;
                }
                                
                                獲取radix
                if (size_flag)
                        index = heap_index - radix_index;
                else
                        index = radix_index;
                                
                                radix和mask&操作,決定insert_node插入left還是right
                if (index & mask)
                                {              
                                                如果right==NULL則直接插入,否則繼續(xù)比較
                        if (prio_tree_right_empty(cur))
                                                {
                                INIT_PRIO_TREE_NODE(node);
                                cur->right = node;
                                node->parent = cur;
                                return res;
                        } else
                                cur = cur->right;
                }
                                else
                                {            
                                               如果left==NULL直接插入,否則繼續(xù)比較
                        if (prio_tree_left_empty(cur))
                                               {
                                INIT_PRIO_TREE_NODE(node);
                                cur->left = node;
                                node->parent = cur;
                                return res;
                        } else
                                cur = cur->left;
                }
                                
                                mask移位,進行下一位的比較操作
                mask >>= 1;

                if (!mask) {
                                                如果mask已經(jīng)到了最低位,則開始利用size進行比較
                        mask = 1UL << (BITS_PER_LONG - 1);
                        size_flag = 1;
                }
        }
        /* Should not reach here */
        BUG();
        return NULL;
}


刪除操作:



//算法核心:刪除一個node,用其heap index比較大的child node來循環(huán)替代就OK了。
void prio_tree_remove(struct prio_tree_root *root, struct prio_tree_node *node)
{
        struct prio_tree_node *cur;
        unsigned long r_index, h_index_right, h_index_left;

        cur = node;
       //找到葉子結(jié)點,找到替換的路徑path
        while (!prio_tree_left_empty(cur) || !prio_tree_right_empty(cur)) {
                if (!prio_tree_left_empty(cur))
                        get_index(root, cur->left, &r_index, &h_index_left);
                else {
                        cur = cur->right;
                        continue;
                }

                if (!prio_tree_right_empty(cur))
                        get_index(root, cur->right, &r_index, &h_index_right);
                else {
                        cur = cur->left;
                        continue;
                }

                /* both h_index_left and h_index_right cannot be 0 */
                //找heap_index大的孩子結(jié)點
                if (h_index_left >= h_index_right)
                        cur = cur->left;
                else
                        cur = cur->right;
        }
       //如果當前結(jié)點是root,則重新初始化下root node
        if (prio_tree_root(cur)) {
                BUG_ON(root->prio_tree_node != cur);
                __INIT_PRIO_TREE_ROOT(root, root->raw);
                return;
        }
        //刪除當前結(jié)點
        if (cur->parent->right == cur)
                cur->parent->right = cur->parent;
        else
                cur->parent->left = cur->parent;
        //循環(huán)向上替代parent結(jié)點
        while (cur != node)
                cur = prio_tree_replace(root, cur->parent, cur);
}

擴展操作:





static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root,struct prio_tree_node *node, unsigned long max_heap_index)
{
        struct prio_tree_node *first = NULL, *prev, *last = NULL;
               
                首先擴展下index_bits,如果不進入while循環(huán),可直接把insert_node當做root節(jié)點。
        if (max_heap_index > prio_tree_maxindex(root->index_bits))
                root->index_bits++;
               
                核心思想:
           1 循環(huán)刪除原來的root_node,然后插入到insert_node的left左子樹上
           2 如果原來的tree最后還是非空,則把整個樹插入到新的樹的left左子樹上

        while (max_heap_index > prio_tree_maxindex(root->index_bits)) {
                root->index_bits++;

                if (prio_tree_empty(root))
                        continue;

                if (first == NULL) {
                        first = root->prio_tree_node;
                        prio_tree_remove(root, root->prio_tree_node);
                        INIT_PRIO_TREE_NODE(first);
                        last = first;
                } else {
                                                此時last=first,而first是樹第一個被刪除的root_node   
                        prev = last;

                                                先刪除root_node
                        last = root->prio_tree_node;
                        prio_tree_remove(root, root->prio_tree_node);

                                                然后把root_node插入prev_node的左子樹上
                        INIT_PRIO_TREE_NODE(last);
                        prev->left = last;
                        last->parent = prev;
                }
        }

        INIT_PRIO_TREE_NODE(node);
               
                【first,last】是原先tree的被刪除的跟節(jié)點集合,并且以left指針相連
           1 然后first掛在node的left子樹上
           2 原來的tree掛在last的left子樹上
           
           操作1
        if (first) {
                node->left = first;
                first->parent = node;
        } else
                last = node;
           
           操作2
                如果此時樹還是非空的,則把樹的剩余部分掛在last的左子樹上
        if (!prio_tree_empty(root)) {
                last->left = root->prio_tree_node;
                last->left->parent = last;
        }
               
                更新root節(jié)點
        root->prio_tree_node = node;
        return node;
}


圖和代碼稍微有點不一樣,就是 被刪除的跟節(jié)點先自己用LEFT指針 組合成LIST
然后在 NODE->LEFT=LIST.HEAD
          LIST.HEAD->LEFT=remain_TREE

論壇徽章:
0
2 [報告]
發(fā)表于 2011-04-24 00:45 |只看該作者
圖非常大,所以下載下來在電腦上結(jié)合代碼看比較清晰。。。。。。

論壇徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵節(jié)徽章
日期:2015-03-06 15:50:392015亞冠之大阪鋼巴
日期:2015-06-12 16:01:352015年中國系統(tǒng)架構(gòu)師大會
日期:2015-06-29 16:11:2815-16賽季CBA聯(lián)賽之四川
日期:2018-12-17 14:10:21
3 [報告]
發(fā)表于 2011-04-24 08:32 |只看該作者
如果我是版主,我會給樓主精華,

論壇徽章:
0
4 [報告]
發(fā)表于 2011-04-24 08:45 |只看該作者
不錯哦!頂一下!

論壇徽章:
0
5 [報告]
發(fā)表于 2011-04-24 10:48 |只看該作者
支持樓主!

論壇徽章:
0
6 [報告]
發(fā)表于 2011-04-24 19:14 |只看該作者
回復 3# T-Bagwell


    謝謝:wink:

論壇徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16賽季CBA聯(lián)賽之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金雞報曉
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年紀念徽章
日期:2016-11-09 13:19:1015-16賽季CBA聯(lián)賽之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序設計版塊每日發(fā)帖之星
日期:2015-12-03 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運維版塊每日發(fā)帖之星
日期:2015-08-09 06:20:002015亞冠之吉達阿赫利
日期:2015-07-03 08:39:42
7 [報告]
發(fā)表于 2011-04-24 19:43 |只看該作者
本帖最后由 amarant 于 2011-04-24 19:44 編輯

圖太大了。。。緩沖了半天。。。。。。。。。。。。
標題中的王者歸來是什么意思呀,應該是愛因斯坦歸來  哈哈

論壇徽章:
0
8 [報告]
發(fā)表于 2011-04-24 19:46 |只看該作者
回復 7# amarant


    怕不清晰,影響閱讀。。。。

論壇徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16賽季CBA聯(lián)賽之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金雞報曉
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年紀念徽章
日期:2016-11-09 13:19:1015-16賽季CBA聯(lián)賽之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序設計版塊每日發(fā)帖之星
日期:2015-12-03 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運維版塊每日發(fā)帖之星
日期:2015-08-09 06:20:002015亞冠之吉達阿赫利
日期:2015-07-03 08:39:42
9 [報告]
發(fā)表于 2011-04-24 19:50 |只看該作者
lz很強啊。收藏了,留著以后仔細讀下

論壇徽章:
36
IT運維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
10 [報告]
發(fā)表于 2011-04-25 18:01 |只看該作者
回復  amarant


    怕不清晰,影響閱讀。。。。
cluter 發(fā)表于 2011-04-24 19:46


多謝 LZ 的分享
可以考慮把圖片搞成附件。

這樣打開頁面確實比較慢
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP