自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入剖析Linux內(nèi)核反向映射機(jī)制

系統(tǒng) Linux
為了系統(tǒng)的安全性,Linux內(nèi)核將各個用戶進(jìn)程運(yùn)行在各自獨(dú)立的虛擬地址空間,用戶進(jìn)程之間通過虛擬地址空間相互隔離,不能相互訪問,一個進(jìn)程的奔潰不會影響到整個系統(tǒng)的異常也不會干擾到系統(tǒng)以及其他進(jìn)程運(yùn)行。

[[353175]]

作者簡介

Cheetah,曾為U-boot社區(qū)和Linux內(nèi)核社區(qū)提交過若干補(bǔ)丁,主要從事Linux相關(guān)系統(tǒng)軟件開發(fā)工作,負(fù)責(zé)Soc芯片BringUp及系統(tǒng)軟件開發(fā),喜歡閱讀內(nèi)核源代碼,在不斷的學(xué)習(xí)和工作中深入理解內(nèi)存管理,進(jìn)程調(diào)度,文件系統(tǒng),設(shè)備驅(qū)動等內(nèi)核子系統(tǒng)。

為了系統(tǒng)的安全性,Linux內(nèi)核將各個用戶進(jìn)程運(yùn)行在各自獨(dú)立的虛擬地址空間,用戶進(jìn)程之間通過虛擬地址空間相互隔離,不能相互訪問,一個進(jìn)程的奔潰不會影響到整個系統(tǒng)的異常也不會干擾到系統(tǒng)以及其他進(jìn)程運(yùn)行。

Linux內(nèi)核可以通過共享內(nèi)存的方式為系統(tǒng)節(jié)省大量內(nèi)存,例如fork子進(jìn)程的時候,父子進(jìn)程通過只讀的方式共享所有的私有頁面。再比如通過IPC共享內(nèi)存方式,各個不相干的進(jìn)程直接可以共享一塊物理內(nèi)存等等。

我們都知道操作系統(tǒng)開啟mmu之后cpu訪問到的都是虛擬地址,當(dāng)cpu訪問一個虛擬地址的時候需要通過mmu將虛擬地址轉(zhuǎn)化為物理地址,這叫做正向映射。而與本文相關(guān)的是反向映射,它主要是通過物理頁來找到共享這個頁的所有的vma對應(yīng)的頁表項(xiàng),這是本文討論的問題。

 

本文目錄:

1.反向映射的發(fā)展

2.反向映射應(yīng)用場景

3.匿名頁的反向映射

4.文件頁的反向映射

5.ksm頁的反向映射

5.總結(jié)

注:反向映射機(jī)制是Linux內(nèi)核虛擬內(nèi)存管理的難點(diǎn)也是理解內(nèi)存管理的關(guān)鍵技術(shù)之一!!

1.反向映射的發(fā)展

實(shí)際上在早期的Linux內(nèi)核版本中是沒有反向映射的這個概念的,那個時候?yàn)榱苏业揭粋€物理頁面對應(yīng)的頁表項(xiàng)就需要遍歷系統(tǒng)中所有的mm組成的鏈表,然后對于每一個mm再遍歷每一個vma,然后查看這個vma是否映射了這頁,這個過程極其漫長而低效,有的時候不得不遍歷完所有的mm然后才能找映射到這個頁的所有pte。

 

后來人們發(fā)現(xiàn)了這個問題,就再描述物理頁面的page結(jié)構(gòu)體中增加一個指針的方式來解決,通過這個指針來找到一個描述映射這個頁的所有pte的數(shù)組結(jié)構(gòu),這對于反向映射查找所有pte易如反掌,但是帶來的是浪費(fèi)內(nèi)存的問題。

 

接著就在2.6內(nèi)核的時候,內(nèi)核大神們想到了復(fù)用page結(jié)構(gòu)中的mapping字段,然后通過紅黑樹的方式來組織所有映射這個頁的vma,形成了匿名頁和文件頁的反向映射機(jī)制。

如下為匿名頁反向映射圖解:

 

如下為文件頁反向映射圖解:

 

但是后來匿名頁的反向映射遇到了效率和鎖競爭激烈問題,就促使了目前使用的通過avc的方式聯(lián)系各層級反向映射結(jié)構(gòu)然后將鎖的粒度降低的這種方式??梢钥吹椒聪蛴成涞陌l(fā)展是伴隨著Linux內(nèi)核的發(fā)展而發(fā)展,是一個不斷進(jìn)行優(yōu)化演進(jìn)的過程。

2.反向映射應(yīng)用場景

那么為何在Linux內(nèi)核中需要反向映射這種機(jī)制呢?它究竟為了解決什么樣的問題而產(chǎn)生的呢?

試想有如下場景:

(1)一個物理頁面被多個進(jìn)程的vma所映射,系統(tǒng)過程中發(fā)生了內(nèi)存不足,需要回收一些頁面,正好發(fā)現(xiàn)這個頁面是適合我們回收利用的,我們能夠直接把這個頁面還給伙伴系統(tǒng)嗎?答案肯定是不能。因?yàn)檫@個頁面被很多個進(jìn)程所共享,我們必須做的事情就是斷開這個頁面的所以映射關(guān)系,這就是反向映射所做的事情。

(2)一些情況我們需要將一個頁面遷移到另一個頁面,但是牽一發(fā)而動全身,可能有一些進(jìn)程已經(jīng)映射這個即將要遷移的頁面到自己的vma中,那么這個時候同樣需要我們知道究竟這個頁面被哪些vma所映射呢?這同樣是反向映射所做的事情。

實(shí)際上,反向映射的主要應(yīng)用場景為內(nèi)存回收和頁面遷移,當(dāng)系統(tǒng)發(fā)生內(nèi)存回收和頁面遷移的時候,對于每一個候選頁Linux內(nèi)核都會判斷是否為映射頁,如果是,就會調(diào)用try_to_unmap 來解除頁表映射關(guān)系,本文也主要來從try_to_unmap函數(shù)來解讀反向映射機(jī)制。

如果我們在細(xì)致到其他的內(nèi)核子系統(tǒng)會發(fā)現(xiàn),在內(nèi)存回收,內(nèi)存碎片整理,CMA, 巨型頁,頁遷移等各個場景中都能發(fā)現(xiàn)反向映射所做的關(guān)鍵性的工作,所有理解反向映射機(jī)制在Linux內(nèi)核中的實(shí)現(xiàn)是理解掌握這些子系統(tǒng)的基礎(chǔ)和關(guān)鍵性所在,否則你即將不能理解這些技術(shù)背后的脊髓所在,所以說理解反向映射這種機(jī)制對于理解Linux內(nèi)核內(nèi)存管理是至關(guān)重要的!!!

3.匿名頁的反向映射

匿名頁的共享主要發(fā)生在父進(jìn)程fork子進(jìn)程的時候,父fork子進(jìn)程時,會復(fù)制所有vma給子進(jìn)程,并通過調(diào)用dup_mmap->anon_vma_fork建立子進(jìn)程的rmap以及和長輩進(jìn)程rmap關(guān)系結(jié)構(gòu):

 

主要通過anon_vma這個數(shù)據(jù)結(jié)構(gòu)體中的紅黑樹將共享父進(jìn)程的頁的所有子進(jìn)程的vma聯(lián)系起來(通過anon_vma_chain 來聯(lián)系對應(yīng)的vma和av),當(dāng)然這個關(guān)系建立比較復(fù)雜,涉及到vma,avc和av這些數(shù)據(jù)結(jié)構(gòu)體。.

而在缺頁異常do_anonymous_page的時候?qū)age和vma相關(guān)聯(lián)。

當(dāng)內(nèi)存回收或頁面遷移的時候,內(nèi)核路徑最終會調(diào)用到:

  1. try_to_unmap //mm/rmap.c 
  2. ->rmap_walk 
  3.   ->rmap_walk_anon 
  4.      ->anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root,pgoff_start, pgoff_end) 
  5.          ->rwc->rmap_one 
  6.             ->try_to_unmap_one 

對于候選頁,會拿到候選頁相關(guān)聯(lián)的anon_vma,然后從anon_vma的紅黑樹中遍歷到所有共享這個頁的vma,然后對于每一個vma通過try_to_unmap_one來處理相對應(yīng)的頁表項(xiàng),將映射關(guān)系解除。

4.文件頁的反向映射

文件頁的共享主要發(fā)生在多個進(jìn)程共享libc庫,同一個庫文件可以只需要讀取到page cache一次,然后通過各個進(jìn)程的頁表映射到各個進(jìn)程的vma中。

管理共享文件頁的所以vma是通過address_space的區(qū)間樹來管理,在mmap或者fork的時候?qū)ma加入到這顆區(qū)間樹中:

 

發(fā)生文件映射缺頁異常的時候,將page和address_space相關(guān)聯(lián)。

當(dāng)內(nèi)存回收或頁面遷移的時候,內(nèi)核路徑最終會調(diào)用到:

  1. try_to_unmap //mm/rmap.c 
  2. ->rmap_walk 
  3.   ->rmap_walk_file 
  4.     ->vma_interval_tree_foreach(vma, &mapping>i_mmap,pgoff_start, pgoff_end)  
  5.          ->rwc->rmap_one 

對于每一個候選的文件頁,如果是映射頁,就會遍歷page所對應(yīng)的address_space的區(qū)間樹,對于每一個滿足條件的vma,調(diào)用try_to_unmap_one來找到pte并解除映射關(guān)系。

5.ksm頁的反向映射

ksm機(jī)制是內(nèi)核將頁面內(nèi)容完全相同的頁面進(jìn)行合并(ksm管理的都是匿名頁),將映射到這個頁面的頁表項(xiàng)標(biāo)記為只讀,然后釋放掉原來的頁表,來達(dá)到節(jié)省大量內(nèi)存的目的,這對于host中開多個虛擬機(jī)的應(yīng)用場景非常有用。

ksm機(jī)制中會管理兩課紅黑樹,一棵是stable tree,一棵是unstable tree,stable tree中的每個節(jié)點(diǎn)stable_node中管理的頁面都是頁面內(nèi)容完全相同的頁面(被叫做kpage),共享kpage的頁面的頁表項(xiàng)都會標(biāo)記為只讀,而且對于原來的候選頁都會有rmap_item來描述他的反向映射(其中的anon_vma成員的紅黑樹是描述映射這個候選頁的所有vma的集合),合并的時候會加入到對應(yīng)的stable tree節(jié)點(diǎn)和鏈表中。

當(dāng)內(nèi)存回收或頁面遷移的時候,內(nèi)核路徑最終會調(diào)用到:

  1. try_to_unmap //mm/rmap.c 
  2. ->rmap_walk 
  3.    ->rmap_walk_ksm  //mm/ksm.c 
  4.         -> hlist_for_each_entry(rmap_item, &stable_node->hlist, hlist) 
  5.     ->anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,0, ULONG_MAX)  
  6.       ->rwc->rmap_one 

對于一個ksm頁面,反向映射的時候,會拿到ksm頁面對應(yīng)的節(jié)點(diǎn),然后遍歷節(jié)點(diǎn)的hlist鏈表,拿到每一個anon_vma,然后就和上面介紹的匿名頁的反向映射一樣了,從anon_vma的紅黑樹中找到所有的vma,最后try_to_unmap_one來找到pte并解除映射關(guān)系。

6.總結(jié)

前面我們介紹了反向映射的三種類型,匿名頁,文件頁和ksm頁的反向映射,分別通過page所對應(yīng)的的vma, address_space, stable_node結(jié)構(gòu)來查找vma。當(dāng)然我們只是介紹了Linux內(nèi)核中的反向映射的冰山一角,主要是try_to_unmap函數(shù),其實(shí)每種反向映射各個數(shù)據(jù)結(jié)構(gòu)建立的過程錯綜復(fù)雜,一篇文章三言兩語也說不清楚,他們散落在Linux內(nèi)核源代碼的進(jìn)程創(chuàng)建fork,內(nèi)存映射mmap,缺頁異常處理,文件系統(tǒng)等各個角落。

誠然,如果我們搞不清楚各種反正映射所對應(yīng)的各種數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系,或者只是有一些概念上的了解,并沒有真正掌握這種機(jī)制的實(shí)現(xiàn)原理,對于我們來理解Linux內(nèi)核虛擬內(nèi)存管理來說是一種障礙,不懂得反向映射內(nèi)存管理 中的很多問題是搞不明白的!

本文轉(zhuǎn)載自微信公眾號「 Linux閱碼場」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系 Linux閱碼場公眾號。

 

責(zé)任編輯:武曉燕 來源: Linux閱碼場
相關(guān)推薦

2011-03-21 09:11:52

Linux頁面回收反向映射

2009-09-28 14:54:33

Hibernate映射

2010-08-04 13:52:53

Flex事件機(jī)制

2025-04-18 04:05:00

2025-04-07 00:01:00

Linux內(nèi)核反向映射

2021-03-06 22:41:06

內(nèi)核源碼CAS

2010-01-07 13:44:54

Linux內(nèi)核代碼

2009-06-17 17:00:03

2010-09-17 12:39:51

JAVA反射機(jī)制

2018-05-18 09:07:43

Linux內(nèi)核內(nèi)存

2021-05-19 07:56:26

Linux內(nèi)核搶占

2017-08-16 16:20:01

Linux內(nèi)核態(tài)搶占用戶態(tài)搶占

2009-10-29 09:41:01

Linux內(nèi)核DeviceMappe

2009-12-23 13:17:36

Linux設(shè)備驅(qū)動

2025-02-12 00:29:58

2025-04-01 02:00:22

2025-04-02 00:33:00

2025-04-22 08:21:10

2025-04-28 02:00:00

2019-07-08 20:00:35

Linux內(nèi)核模塊
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號