linux內(nèi)存回收機制

1回收哪些頁面

發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認真做好每個細節(jié),不斷完善自我,成就企業(yè),實現(xiàn)共贏。行業(yè)涉及成都鑿毛機等,在重慶網(wǎng)站建設(shè)公司、全網(wǎng)整合營銷推廣、WAP手機網(wǎng)站、VI設(shè)計、軟件開發(fā)等項目上具有豐富的設(shè)計經(jīng)驗。

Page cache;

用戶地址空間的內(nèi)存映射頁面;

Slab緩存:如dentry和inode cache;

匿名頁:進程堆棧和mmap匿名映射內(nèi)存區(qū);回收前先換置到swap;

 

 

2何時回收

Kswapd定期喚醒:當(dāng)系統(tǒng)空閑內(nèi)存小于閾值則進行頁面回收;

直接頁面回收:假設(shè)操作系統(tǒng)需要通過伙伴系統(tǒng)為用戶進程分配一大塊內(nèi)存,或者需要創(chuàng)建一個很大的緩沖區(qū),而當(dāng)時系統(tǒng)中的內(nèi)存沒有辦法提供足夠多的物理內(nèi)存以滿足這種內(nèi)存請求,這時候,操作系統(tǒng)就必須盡快進行頁面回收操作;

OS嘗試內(nèi)存回收后仍無法獲取足夠頁面,則調(diào)用find_bad_process并進行OOM kill;

 

 

3如何回收

基于LRU算法;每個zone維護兩個LRU鏈表

struct zone {

    ……

          spinlock_t                   lru_lock;          

          struct list_head   active_list;

          struct list_head     inactive_list;

          unsigned long                  nr_active;

          unsigned long                  nr_inactive;

    ……

        

 }

PG_active/PG_referenced用于標(biāo)識頁面活躍度,前者標(biāo)識頁面時活躍的;后者表示頁面最近是否被訪問過,每訪問一次便會置位;

注:假如只是用一個標(biāo)志符,在頁面被訪問時,置位該標(biāo)志符,之后該頁面一直處于活躍狀態(tài),如果操作系統(tǒng)不清除該標(biāo)志位,那么即使之后很長一段時間內(nèi)該頁面都沒有或很少被訪問過,該頁面也還是處于活躍狀態(tài)。為了能夠有效清除該標(biāo)志位,需要有定時器的支持以便于在超時時間之后該標(biāo)志位可以自動被清除。然而,很多 Linux支持的體系結(jié)構(gòu)并不能提供這樣的硬件支持,所以 Linux中使用兩個標(biāo)志符來判斷頁面的活躍程度。

 

Linux依據(jù)這兩個字段將page在active_list和inactive_list之間移動;
linux內(nèi)存回收機制

注:1表示函數(shù) mark_page_accessed(),2表示函數(shù) page_referenced(),3表示函數(shù) activate_page(),4表示函數(shù) shrink_active_list()
linux內(nèi)存回收機制


 

不管是kswapd還是直接頁面回收,最終都調(diào)用shrink_slab和shrink_zone;

直接頁面回收:反復(fù)調(diào)用這兩個函數(shù),若特定循環(huán)次數(shù)內(nèi)沒能成功釋放N個page,則調(diào)用OOM killer;

Kswapd:對每個zone都調(diào)用shrink_zone();

 

3.1 Shrink_slab原理

先向操作系統(tǒng)內(nèi)核注冊 shrinker函數(shù),會在內(nèi)存較少的時候主動釋放一些該磁盤緩存占用的空間。

函數(shù) shrink_slab()會遍歷 shrinker鏈表,從而對所有注冊了 shrinker函數(shù)的磁盤緩存進行處理。

注冊 shrinker是通過函數(shù) set_shrinker()實現(xiàn)的,解除 shrinker注冊是通過函數(shù) remove_shrinker()實現(xiàn)的。當(dāng)前,Linux操作系統(tǒng)中主要的 shrinker函數(shù)有如下幾種:

shrink_dcache_memory():該 shrinker函數(shù)負責(zé) dentry緩存。

shrink_icache_memory():該 shrinker函數(shù)負責(zé) inode緩存。

mb_cache_shrink_fn():該 shrinker函數(shù)負責(zé)用于文件系統(tǒng)元數(shù)據(jù)的緩存。

 

3.2 Shrink_zone原理

1通過shrink_active_list()將頁面從active移到inactive list;

2調(diào)用shrink_inactive_list()將inactive list的頁放入臨時鏈表,最終調(diào)用shrink_page_list()回收
linux內(nèi)存回收機制


 

3.2.1 Swappiness的意義

上文提到的shrink_zone()會調(diào)用 shrink_lruvec(),而active/inactive list又各分為anon匿名頁和file cache映射頁鏈表,總計4個LRU;

而swappines只針對anon page,即便其為0也有可能執(zhí)行swap。

vmscan.c中的get_scan_coun()

1.首先如果系統(tǒng)禁用了swap或者沒有swap空間,則只掃描file based的鏈表,即不進行匿名頁鏈表掃描

 代碼:

       if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {

                scan_balance = SCAN_FILE;

                goto out;

        }

 

2.如果當(dāng)前進行的不是全局頁回收(cgroup資源限額引起的頁回收),并且swappiness設(shè)為0,則不進行匿名頁鏈表掃描,

代碼:

        if (!global_reclaim(sc) && !vmscan_swappiness(sc)) {

                scan_balance = SCAN_FILE;

                goto out;

        }

 

3.如果進行鏈表掃描前設(shè)置的priority(這個值決定掃描多少分之一的鏈表元素)為0,且swappiness非0,則可能會進行swap

代碼:

        if (!sc->priority && vmscan_swappiness(sc)) {

                scan_balance = SCAN_EQUAL;

                goto out;

        }

 

4.如果是全局頁回收,并且當(dāng)前空閑內(nèi)存和所有file based鏈表page數(shù)目的加和都小于系統(tǒng)的high watermark,則必須進行匿名頁回收,則必然會發(fā)生swap

代碼:

        anon  = get_lru_size(lruvec, LRU_ACTIVE_ANON) +

                get_lru_size(lruvec, LRU_INACTIVE_ANON);

        file  = get_lru_size(lruvec, LRU_ACTIVE_FILE) +

                get_lru_size(lruvec, LRU_INACTIVE_FILE);

 

        if (global_reclaim(sc)) {

                free = zone_page_state(zone, NR_FREE_PAGES);

                if (unlikely(file + free <= high_wmark_pages(zone))) {

                       scan_balance = SCAN_ANON;

                        goto out;

                }

        }

 

5.如果系統(tǒng)inactive file鏈表比較充足,則不考慮進行匿名頁的回收,即不進行swap

代碼:

        if (!inactive_file_is_low(lruvec)) {

                scan_balance = SCAN_FILE;

                goto out;

        }

注:每個zone有min/low/high 3個值,而high watermark指的是最后一個,這3個值依據(jù)vm.min_free_kbytes設(shè)置

 

 

3.2.2反向映射

回收物理頁前需要解除所有關(guān)聯(lián)該頁的頁表項,而共享內(nèi)存中的頁可能被多個進程引用,因此需要一種機制快速定位頁表項;

2.4要遍歷所有進程;

2.5引入反向映射,每個物理頁維護一個頁表項鏈表;

2.6引入基于對象的反向映射,每個物理頁設(shè)置一個反向映射鏈表,鏈表節(jié)點為vm_area_struct結(jié)構(gòu),其通過mm_struct找到pgd進而找到相應(yīng)頁表項;

struct page {

          atomic_t _mapcount; --初始值是 -1,每增加一個使用者,該計數(shù)器加 1

          union {

        ……

             struct {

                   ……           

                    struct address_space *mapping; --如果最低位置位,為指向 anon_vma結(jié)構(gòu)(用于匿名頁面)的指針;否則為 address_space指針(用于基于文件映射的頁面)。

             };

        ……

 };

對于匿名頁面來說,頁面雖然可以是共享的,但是一般情況下,共享匿名頁面的使用者的數(shù)目不會很多;而對于基于文件映射的頁面來說,共享頁面的使用者的數(shù)目可能會非常多,使用優(yōu)先級搜索樹這種結(jié)構(gòu)可以更加快速地定位那些引用了該頁面的虛擬內(nèi)存區(qū)域。操作系統(tǒng)會為每一個文件都建立一個優(yōu)先級搜索樹,其根節(jié)點可以通過結(jié)構(gòu) address_space中的 i_mmap字段獲取。

linux內(nèi)存回收機制

 

 

 

注:LRU緩存

頁面根據(jù)其活躍程度會在 active鏈表和 inactive鏈表之間來回移動,如果要將某個頁面插入到這兩個鏈表中去,必須要通過自旋鎖以保證對鏈表的并發(fā)訪問操作不會出錯。為了降低鎖的競爭,Linux提供了一種特殊的緩存:LRU緩存,用以批量地向 LRU鏈表中快速地添加頁面。有了 LRU緩存之后,新頁不會被馬上添加到相應(yīng)的鏈表上去,而是先被放到一個緩沖區(qū)中去,當(dāng)該緩沖區(qū)緩存了足夠多的頁面之后,緩沖區(qū)中的頁面才會被一次性地全部添加到相應(yīng)的 LRU鏈表中去。

LRU緩存用到了 pagevec結(jié)構(gòu),如下所示 :

 struct pagevec {

          unsigned long nr;

          unsigned long cold;

          struct page *pages[PAGEVEC_SIZE];

 };

lru_cache_add()和 lru_cache_add_active()。前者用于延遲將頁面添加到 inactive鏈表上去,后者用于延遲將頁面添加到 active鏈表上去。這兩個函數(shù)都會將要移動的頁面先放到頁向量 pagevec中,當(dāng) pagevec滿了(已經(jīng)裝了 14個頁面的描述符指針),pagevec結(jié)構(gòu)中的所有頁面才會被一次性地移動到相應(yīng)的鏈表上去。

 

 

 

參考資料

http://www.ibm.com/developerworks/cn/linux/l-cn-pagerecycle/index.html?ca=dat

http://www.douban.com/note/349467816/

 

 

本文名稱:linux內(nèi)存回收機制
文章路徑:http://muchs.cn/article30/pidipo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、微信公眾號、定制開發(fā)品牌網(wǎng)站設(shè)計、云服務(wù)器、動態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)