【原創】(十五)Linux記憶體管理之RMAP
背景
Read the fucking source code!
--By 魯迅A picture is worth a thousand words.
--By 高爾基
說明:
- Kernel版本:4.14
- ARM64處理器,Contex-A53,雙核
- 使用工具:Source Insight 3.5, Visio
1. 概述
RMAP反向對映
是一種實體地址反向對映虛擬地址的方法。
對映
頁表用於虛擬地址到實體地址對映,其中的PTE
頁表項記錄了對映關係,同時struct page
結構體中的mapcount
欄位儲存了有多少PTE
頁表項映射了該物理頁。反向對映
當某個實體地址要進行回收或遷移時,此時需要去找到有多少虛擬地址射在該實體地址,並斷開對映處理。在沒有反向對映的機制時,需要去遍歷程序的頁表,這個效率顯然是很低下的。反向對映可以找到虛擬地址空間VMA
VMA
使用的使用者頁表中取消對映,可以快速解決這個問題。
反向對映的典型應用場景:
kswapd
進行頁面回收時,需要斷開所有映射了該匿名頁面的PTE表項;- 頁面遷移時,需要斷開所有映射了該匿名頁面的PTE表項;
2. 資料結構
反向對映有三個關鍵的結構體:
struct vm_area_struct
,簡稱VMA
;
VMA
我們在之前的文章中介紹過,用於描述程序地址空間中的一段區域。與反向對映相關的欄位如下:
struct vm_area_struct { ... /* * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma * list, after a COW of one of the file pages. A MAP_SHARED vma * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack * or brk vma (with NULL file) can only be in an anon_vma list. */ struct list_head anon_vma_chain; /* Serialized by mmap_sem & * page_table_lock */ struct anon_vma *anon_vma; /* Serialized by page_table_lock */ ... }
struct anon_vma
,簡稱AV
;
AV
結構用於管理匿名型別VMAs
,當有匿名頁需要unmap
處理時,可以先找到AV
,然後再通過AV
進行查詢處理。結構如下:
/* * The anon_vma heads a list of private "related" vmas, to scan if * an anonymous page pointing to this anon_vma needs to be unmapped: * the vmas on the list will be related by forking, or by splitting. * * Since vmas come and go as they are split and merged (particularly * in mprotect), the mapping field of an anonymous page cannot point * directly to a vma: instead it points to an anon_vma, on whose list * the related vmas can be easily linked or unlinked. * * After unlinking the last vma on the list, we must garbage collect * the anon_vma object itself: we're guaranteed no page can be * pointing to this anon_vma once its vma list is empty. */ struct anon_vma { struct anon_vma *root; /* Root of this anon_vma tree */ struct rw_semaphore rwsem; /* W: modification, R: walking the list */ /* * The refcount is taken on an anon_vma when there is no * guarantee that the vma of page tables will exist for * the duration of the operation. A caller that takes * the reference is responsible for clearing up the * anon_vma if they are the last user on release */ atomic_t refcount; /* * Count of child anon_vmas and VMAs which points to this anon_vma. * * This counter is used for making decision about reusing anon_vma * instead of forking new one. See comments in function anon_vma_clone. */ unsigned degree; struct anon_vma *parent; /* Parent of this anon_vma */ /* * NOTE: the LSB of the rb_root.rb_node is set by * mm_take_all_locks() _after_ taking the above lock. So the * rb_root must only be read/written after taking the above lock * to be sure to see a valid next pointer. The LSB bit itself * is serialized by a system wide lock only visible to * mm_take_all_locks() (mm_all_locks_mutex). */ /* Interval tree of private "related" vmas */ struct rb_root_cached rb_root; };
struct anon_vma_chain
,簡稱AVC
;
AVC
是連線VMA
和AV
之間的橋樑。
/*
* The copy-on-write semantics of fork mean that an anon_vma
* can become associated with multiple processes. Furthermore,
* each child process will have its own anon_vma, where new
* pages for that process are instantiated.
*
* This structure allows us to find the anon_vmas associated
* with a VMA, or the VMAs associated with an anon_vma.
* The "same_vma" list contains the anon_vma_chains linking
* all the anon_vmas associated with this VMA.
* The "rb" field indexes on an interval tree the anon_vma_chains
* which link all the VMAs associated with this anon_vma.
*/
struct anon_vma_chain {
struct vm_area_struct *vma;
struct anon_vma *anon_vma;
struct list_head same_vma; /* locked by mmap_sem & page_table_lock */
struct rb_node rb; /* locked by anon_vma->rwsem */
unsigned long rb_subtree_last;
#ifdef CONFIG_DEBUG_VM_RB
unsigned long cached_vma_start, cached_vma_last;
#endif
};
來一張圖就清晰明瞭了:
- 通過
same_vma
連結串列節點,將anon_vma_chain
新增到vma->anon_vma_chain
連結串列中; - 通過
rb
紅黑樹節點,將anon_vma_chain
新增到anon_vma->rb_root
的紅黑樹中;
2. 流程分析
先看一下巨集觀的圖:
- 地址空間
VMA
可以通過頁表完成虛擬地址到實體地址的對映; - 頁框與
page
結構對應,page
結構中的mapping
欄位指向anon_vma
,從而可以通過RMAP
機制去找到與之關聯的VMA
;
2.1 anon_vma_prepare
之前在page fault
的文章中,提到過anon_vma_prepare
函式,這個函式完成的工作就是為程序地址空間中的VMA
準備struct anon_vma
結構。
呼叫例程及函式流程如下圖所示:
至於VMA,AV,AVC
三者之間的關聯關係,在上文的圖中已經有所描述。
當建立了與VMA
關聯的AV
後,還有關鍵的一步需要做完,才能算是真正的把RMAP
通路打通,那就是讓page
與AV
關聯起來。只有這樣才能通過page
找到AV
,進而找到VMA
,從而完成對應的PTE unmap
操作。
2.2 子程序建立anon_vma
父程序通過fork()
來建立子程序,子程序會複製整個父程序的地址空間及頁表。子程序拷貝了父程序的VMA
資料結構內容,而子程序建立相應的anon_vma
結構,是通過anon_vma_fork()
函式來實現的。
anon_vma_fork()
效果圖如下:
以實際fork()
兩次為例,發生COW
之後,看看三個程序的連結關係,如下圖:
2.3 TTU(try to unmap)
和Rmap Walk
如果有page
被對映到多個虛擬地址,可以通過Rmap Walk機制
來遍歷所有的VMA
,並最終呼叫回撥函式來取消對映。
與之相關的結構體為struct rmap_walk_control
,如下:
/*
* rmap_walk_control: To control rmap traversing for specific needs
*
* arg: passed to rmap_one() and invalid_vma()
* rmap_one: executed on each vma where page is mapped
* done: for checking traversing termination condition
* anon_lock: for getting anon_lock by optimized way rather than default
* invalid_vma: for skipping uninterested vma
*/
struct rmap_walk_control {
void *arg;
/*
* Return false if page table scanning in rmap_walk should be stopped.
* Otherwise, return true.
*/
bool (*rmap_one)(struct page *page, struct vm_area_struct *vma,
unsigned long addr, void *arg);
int (*done)(struct page *page);
struct anon_vma *(*anon_lock)(struct page *page);
bool (*invalid_vma)(struct vm_area_struct *vma, void *arg);
};
取消對映的入口為try_to_unmap
,流程如下圖所示:
基本的套路就是圍繞著struct rmap_walk_control
結構,初始化回撥函式,以便在適當的時候能呼叫到。
關於取消對映try_to_unmap_one
的詳細細節就不進一步深入了,把握好大體框架即可。
相關推薦
【原創】(十五)Linux記憶體管理之RMAP
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十二)Linux記憶體管理之vmap與vmalloc
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十四)Linux記憶體管理之page fault處理
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十六)Linux記憶體管理之CMA
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十一)Linux記憶體管理slub分配器
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【SpringCloud】(十五):Zuul的基本應用,反向代理和負載均衡
Router and Filter: Zuul。 Zuul is a JVM based router and server side load balancer by Netflix。 Zu
【原創】(十三)Linux記憶體管理之vma/malloc/mmap
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
Linux系列教程(十五)——Linux用戶和用戶組管理之用戶管理命令
總結 usr 而且 ron 初始 切換 密碼規則 一個 郵箱目錄 上篇博客我們介紹了用戶管理的相關配置文件,包括用戶信息文件/etc/passwd,用戶密碼文件/etc/shadow;然後介紹了用戶組信息文件/etc/group,用戶組密碼文件/etc/gshadow。
Linux(十五)進程管理
終端 kill CI 無法 rip uid 進程管理 僵屍進程 停止 15.1 進程的基本介紹 (1)在linux中,每個執行的程序都稱為一個進程,每一個進程都分配一個ID號。 (2)每一個進程都會對應一個父進程,而這個父進程可以復制多個子線程。例如:www服務器 (3)每
java程式設計師菜鳥進階(十五)linux基礎入門(三)linux使用者和組管理
我們大家都知道,要登入linux作業系統,我們必須要有一個使用者名稱和密碼。每一個使用者都由一個惟一的身份來標識,這個標識叫做使用者ID.系統中的每一個使用者也至少需要屬於一個"使用者分組".同樣,使用者分組也是由一個惟一的身份來標識的,該標識叫做使用者分組ID(GID).每位使用者的許可
Linux初級運維(十五)——bash指令碼程式設計之函式
一、函式 函式:功能,function 程式碼重用的功能。 結構化程式設計,不能獨立執行,需要呼叫
深度學習筆記——理論與推導之Structured Learning【NLP】(十二)
Language Technology Meaning of Word(一個vector表示一個word) Predicting the next word 給一串sequence of words,預測下一個單詞 我們現在要做的就是將wi
【SpringCloud】(十一):超時機制和斷路器及 Hystrix簡單實踐
上篇文章我們配置了Eureka叢集,實現了高可用。在微服務框架中,一個服務消費者可能是其他服務消費者的提供者,而當低層次的服務提供者出現問題時,會導致系統資源被耗盡。出現雪崩效應。 Hystri
【SpringCloud】(十四):Feign對Hystrix的支援 fallbackFactory
前面的文章中提到了fallback,這裡我們描述一個它的增強版。fallbackFactory。都是實現斷路器的功能。 UserFeignClient package com.dynam
Linux初級運維(十四)——Linux軟體管理
一、軟體包管理 1、應用程式: 程式,Architecture C語言:原始碼-->(編譯
從程式設計師到專案經理(十五):專案管理三大目標
專案管理的三大目標即時間、成本和質量,實際是告訴專案經理應重點關注什麼因素,專案控制應該做什麼工作。三大目標雖然簡單,但如果能將其真正貫徹到自己的行動中,那麼對專案計劃制定、過程控制等工作,均能起到引導作用。有了努力的方向,專案經理也就可以真正告別“盲目”了。
(五)Linux記憶體管理zone_sizes_init
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
(十五)、shell指令碼之簡單控制流結構
一、基本的控制結構 1、控制流 常見的控制流就是if、then、else語句提供測試條件,測試條件可以基於各種條件。例如建立檔案是否成功、是否有讀寫許可權等,凡是執行的操作有失敗的可能就可以用控制流,注意控制流的真為0,假為1。 單層if語句 if 條件;then &nbs
【linux】Valgrind工具集詳解(十五):Callgrind(效能分析圖)
一、概述 1、Callgrind Callgrind用於記錄程式中函式之間的呼叫歷史資訊,對程式效能分析。預設情況下,收集的資料包括執行的指令數,它們與原始碼行的關係,函式之間的呼叫者、被呼叫者關係以及此類呼叫的數量。可選項是,對快取記憶體模擬和分支預測(類似於Cachegrin
【原創】(五)Linux程序排程-CFS排程器
# 背景 - `Read the fucking source code!` --By 魯迅 - `A picture is worth a thousand words.` --By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex-A53,雙核 3. 使用工具:S