Linux中的冷熱頁機制概述
什麼是冷熱頁?
在Linux Kernel的實體記憶體管理的Buddy System中,引入了冷熱頁的概念。冷頁表示該空閒頁已經不再快取記憶體中了(一般是指L2 Cache),熱頁表示該空閒頁仍然在快取記憶體中。冷熱頁是針對於每CPU的,每個zone中,都會針對於所有的CPU初始化一個冷熱頁的per-cpu-pageset.
為什麼要有冷熱頁?
作用有3點:
- Buddy Allocator在分配order為0的空閒頁的時候,如果分配一個熱頁,那麼由於該頁已經存在於L2 Cache中了。CPU寫訪問的時候,不需要先把記憶體中的內容讀到Cache中,然後再寫。如果分配一個冷頁,說明該頁不在L2 Cache中。一般情況下,儘可能用熱頁,是容易理解的。什麼時候用冷頁呢?While allocating a physical page frame, there is a bit specifying whether we would like a hot or a cold page (that is, a page likely to be in the CPU cache, or a page not likely to be there). If the page will be used by the CPU, a hot page will be faster. If the page will be used for device
DMA
the CPU cache would be invalidated anyway, and a cold page does not waste precious cache contents.
簡單翻譯一下:當核心分配一個
物理頁框時,有一些規範來約束我們是分配熱頁還是冷頁。當頁框是CPU使用的,則分配熱頁。當頁框是DMA裝置使用的,則分配冷頁。因為DMA裝置不會用到CPU快取記憶體,所以沒必要使用熱頁。 - Buddy System在給某個程式分配某個zone中空閒頁的時候,首先需要用自旋鎖鎖住該zone,然後分配頁。這樣,如果多個CPU上的程式同時進行分配頁,便會競爭。引入了per-cpu-set後,當多個CPU上的程式同時分配頁的時候,競爭便不會發生,提高了效率。另外當釋放單個頁面時,空閒頁面首先放回到per-cpu-pageset中,以減少zone中自旋鎖的使用。當頁面快取中的頁面數量超過閥值時,再將頁面放回到夥伴系統中。
- 使用每CPU冷熱頁還有一個好處是,能保證某個頁一直黏在1個CPU上,這有助於提高Cache的命中率。
冷熱頁的資料結構
struct per_cpu_pages { int count; // number of pages in the list int high; // high watermark, emptying needed int batch; // chunk size for buddy add/remove // Lists of pages, one per migrate type stored on the pcp-lists 每個CPU在每個zone上都有MIGRATE_PCPTYPES個冷熱頁連結串列(根據遷移型別劃分) struct list_head lists[MIGRATE_PCPTYPES]; };
在Linux中,對於UMA的架構,冷熱頁是在一條連結串列上進行管理。熱頁在前,冷頁在後。CPU每釋放一個order為0的頁,如果per-cpu-pageset中的頁數少於其指定的閾值,便會將釋放的頁插入到冷熱頁連結串列的開始處。這樣,之前插入的熱頁便會隨著其後熱頁源源不斷的插入向後移動,其頁由熱變冷的機率便大大增加。
怎樣分配冷熱頁
在分配order為0頁的時候(冷熱頁機制只處理單頁分配的情況),先找到合適的zone,然後根據需要的migratetype
型別定位冷熱頁連結串列(每個zone,對於每個cpu,有3條冷熱頁連結串列,對應於:MIGRATE_UNMOVABLE、MIGRATE_RECLAIMABLE、MIGRATE_MOVABLE)。若需要熱頁,則從連結串列頭取下一頁(此頁最“熱”);若需要冷頁,則從連結串列尾取下一頁(此頁最“冷”)。
分配函式(關鍵部分已新增註釋):
/* * Really, prep_compound_page() should be called from __rmqueue_bulk(). But * we cheat by calling it from here, in the order > 0 path. Saves a branch * or two. */ static inline struct page *buffered_rmqueue(struct zone *preferred_zone, struct zone *zone, int order, gfp_t gfp_flags, int migratetype) { unsigned long flags; struct page *page; //分配標誌是__GFP_COLD才分配冷頁 int cold = !!(gfp_flags & __GFP_COLD); again: if (likely(order == 0)) { struct per_cpu_pages *pcp; struct list_head *list; local_irq_save(flags); pcp = &this_cpu_ptr(zone->pageset)->pcp; list = &pcp->lists[migratetype]; if (list_empty(list)) { //如果缺少頁,則從Buddy System中分配。 pcp->count += rmqueue_bulk(zone, 0, pcp->batch, list, migratetype, cold); if (unlikely(list_empty(list))) goto failed; } if (cold) //分配冷頁時,從連結串列尾部分配,list為連結串列頭,list->prev表示連結串列尾 page = list_entry(list->prev, struct page, lru); else //分配熱頁時,從連結串列頭分配 page = list_entry(list->next, struct page, lru); //分配完一個頁框後從冷熱頁連結串列中刪去該頁 list_del(&page->lru); pcp->count--; } else {//如果order!=0(頁框數>1),則不從冷熱頁連結串列中分配 if (unlikely(gfp_flags & __GFP_NOFAIL)) { /* * __GFP_NOFAIL is not to be used in new code. * * All __GFP_NOFAIL callers should be fixed so that they * properly detect and handle allocation failures. * * We most definitely don't want callers attempting to * allocate greater than order-1 page units with * __GFP_NOFAIL. */ WARN_ON_ONCE(order > 1); } spin_lock_irqsave(&zone->lock, flags); page = __rmqueue(zone, order, migratetype); spin_unlock(&zone->lock); if (!page) goto failed; __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order)); } __count_zone_vm_events(PGALLOC, zone, 1 << order); zone_statistics(preferred_zone, zone, gfp_flags); local_irq_restore(flags); VM_BUG_ON(bad_range(zone, page)); if (prep_new_page(page, order, gfp_flags)) goto again; return page; failed: local_irq_restore(flags); return NULL; }
參考:
- 認識Linux/ARM 中的冷熱頁
- Linux原始碼
相關文章
- 零頁面機制在缺頁中斷中的作用
- Linux中的保護機制Linux
- 概述javascript部分核心機制JavaScript
- 概述nodejs核心機制NodeJS
- Windows訊息機制概述Windows
- Linux中的許可權機制Linux
- 【冷熱分離】
- Linux中斷機制分析Linux
- [譯] 熱的 Vs 冷的 Observables
- Webpack 熱更新機制Web
- Linux記憶體定址之分頁機制Linux記憶體
- Linux 記憶體定址之分頁機制Linux記憶體
- 分頁機制
- SSL/TLS協議執行機制的概述TLS協議
- linux中斷底半部機制Linux
- 理解Linux 中sed命令的工作機制Linux
- 冷飯新炒 | 深入Quartz核心執行機制quartz
- 頁面渲染機制
- 熱資料&冷資料
- MongoDB副本集故障恢復機制概述MongoDB
- openstack下熱遷移機制
- 歸納熱備份機制
- jdon 的分頁機制的效率低,
- mysql的冷備份與熱備份MySql
- oracle的熱備份和冷備份Oracle
- 80386的分段機制、分頁機制和實體地址的形成
- mySql\oracle分頁機制MySqlOracle
- 從Java的類載入機制談起:聊聊Java中如何實現熱部署(熱載入)Java熱部署
- ELK冷熱資料分離
- Linux的安全機制(轉)Linux
- 中國服務機器人市場怪象:產業熱 但投資冷機器人產業
- 【機制】js中的this指向JS
- Java 中的 反射機制Java反射
- ListView 中的 RecycleBin 機制View
- oracle中的鎖機制Oracle
- 冷門的 Java 應用程式安全沙箱機制瞭解一下Java
- Linux OOM 機制LinuxOOM
- Linux安全機制Linux