天天看點

頁面回收分析之二

函數分析-----page_check_references shrink_active_list  mark_page_accessed

首先看看頁面掃描回收大概過程, 然後分析三個函數如何進行頁面狀态變換

1.首先掃描非活躍連結清單中,然後當空閑頁面不夠時,掃描活動連結清單,并将相應頁面狀态變換。

2.然後回收非活躍連結清單,沒有設定頁描述符的字段 flags位PG_referenced頁。

一.mark_page_accessed函數

mark_page_accessed函數設定頁框通路狀态,并進行頁面狀态裝換,。(PG_active,PG_referenced)

(0,1)--->(1,0)

(1,0)--->(1,1)

(0,0)--->(0,1)

頁面狀态裝換圖如下:

 第一個if語句:

将頁面狀态由 inactive,referenced   轉換為  active,unreferenced  即:(0,1)--->(1,0)

将頁面放入活動連結清單,并清空頁描述符的字段 flags位PG_referenced值

第二個if語句:

将頁面狀态由 active,unreferenced     轉換為    active,referenced 即:(1,0)--->(1,1)

仍舊保持在活動連結清單,并設定頁描述符的字段 flags位PG_referenced值

将頁面狀态由 inactive,unreferenced  轉換為    inactive,referenced 即:(0,0)--->(0,1)

仍舊保持在非活動連結清單,并設定頁描述符的字段 flags位PG_referenced值

void mark_page_accessed(struct page *page)

{

         if (!PageActive(page) && !PageUnevictable(page) &&

                        PageReferenced(page) && PageLRU(page)) {

                activate_page(page);

                ClearPageReferenced(page);

        } else if (!PageReferenced(page)) {

                SetPageReferenced(page);

        }

}

由此可見:

(0,0)--->(1,0)需要經過如下過程:

(0,0)--->(0,1) 和 (0,1)--->(1,0) 也就說不活躍連結清單中,沒有引用的頁面,需要兩次通路,才能放入活動連結清單

二.shrink_active_list函數

shrink_active_list函數将活動連結清單裝換為活動連結清單。頁面狀态裝換圖如下:

(1,0)---->(0,0)

(1,1)---->(0,1)

第一個if語句将(1,1)轉換為(0,1),但是有條件的。

其他情況直接轉換。

static void shrink_active_list(unsigned long nr_pages, struct zone *zone,

                        struct scan_control *sc, int priority, int file)

{

   if (page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {

                        nr_rotated += hpage_nr_pages(page);

                        if ((vm_flags & VM_EXEC) && page_is_file_cache(page)) {

                                list_add(&page->lru, &l_active);

                                continue;

                        }

                }

                ClearPageActive(page); 

                list_add(&page->lru, &l_inactive);

}

三.page_check_references

page_check_references函數傳回頁框狀态,并進行頁框狀态轉換(匿名頁特殊處理)。

如果此時頁框,沒有使用者通路頁框(可進行回收):

(0,1)->(0,0)

(0,0)->

如果此時頁框,由使用者通路頁框

(0,1)->(1,0)

(0,0)->(0,1)

前提:

頁框頁在非活躍連結清單

概念:

頁表項:

頁表儲存頁表項,頁表項儲存指向頁框的實體位址和頁框狀态位。其中第6為A(Accessed)位。當讀寫頁框時,作業系統這一位設定1, 當程序退出了,相應頁表項回收,并清空。

頁框描述符:

頁框描述符有一個字段 _mapcount,儲存指向頁框的頁表項數目。計數從-1開始,這個值意味着沒有頁表項指向頁框。如果計數為0,頁框不是共享的,如果大于1,頁框是共享的。

頁框描述符字段 flags位PG_referenced PG_reclaim 用于頁面回收對于 anonymous and file-backed pagecache

page_mapcount( )函數

參數頁框的描述符,傳回結果為_mapcount+1(例如1,為非共享)

page_mapped()函數

如果指向頁框的頁表項數目大于0,傳回真

page_check_references函數代碼過程:

1.擷取指向頁框的頁表項中,A(Accessed)位值, 置1意味着否有程序通路了該頁。

2.擷取頁描述符的字段 flags位PG_referenced值

3.如果A(Accessed)位值, 置1意味着否有程序通路了該頁, 如果該頁是匿名頁,該頁傳回活動連結清單, 否則設定頁框描述符字段 flags位PG_referenced,如果上次頁描述符的字段 flags位PG_referenced值為1,把該頁放入活動連結清單。否則仍舊儲存在非活動連結清單。

4.如果A(Accessed)位值為0, 上次頁描述符的字段 flags位PG_referenced值為1,頁是幹淨的(clean),可進行回收

5.如果A(Accessed)位值為0, 上次頁描述符的字段 flags位PG_referenced值為0, 可進行回收

由此可見:

對于不活躍連結清單中匿名頁,隻需要一次通路,可放入活動連結清單

不活躍連結清單中匿名頁,需要兩次通路,才能放入活動連結清單

static enum page_references page_check_references(struct page *page,

                          struct scan_control *sc)

{

    int referenced_ptes, referenced_page;

    unsigned long vm_flags;

    referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);

    referenced_page = TestClearPageReferenced(page);

    if (vm_flags & VM_LOCKED)

        return PAGEREF_RECLAIM;

    if (referenced_ptes) {

        if (PageAnon(page))

            return PAGEREF_ACTIVATE;

        SetPageReferenced(page);

        if (referenced_page)

            return PAGEREF_ACTIVATE;

        return PAGEREF_KEEP;

    }

    if (referenced_page)

        return PAGEREF_RECLAIM_CLEAN;

    return PAGEREF_RECLAIM;

}