成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

帶你了解內核如何管理內存

系統(tǒng) Linux
在學習了進程的 虛擬地址布局 之后,讓我們回到內核,來學習它管理用戶內存的機制。Linux 進程在內核中是作為進程描述符 task_struct (LCTT 譯注:它是在 Linux 中描述進程完整信息的一種數據結構)的實例來實現的。

[[221177]]

在學習了進程的 虛擬地址布局 之后,讓我們回到內核,來學習它管理用戶內存的機制。這里再次使用 Gonzo:

Linux kernel mm_struct

Linux kernel mm_struct

Linux 進程在內核中是作為進程描述符 task_struct (LCTT 譯注:它是在 Linux 中描述進程完整信息的一種數據結構)的實例來實現的。在 task_struct 中的  mm  域指向到內存描述符mm_struct 是一個程序在內存中的執(zhí)行摘要。如上圖所示,它保存了起始和結束內存段,進程使用的物理內存頁面的 數量(RSS 常駐內存大小Resident Set Size )、虛擬地址空間使用的 總數量、以及其它片斷。 在內存描述符中,我們可以獲悉它有兩種管理內存的方式:虛擬內存區(qū)域集和頁面表。Gonzo 的內存區(qū)域如下所示:

Kernel memory descriptor and memory areas

Kernel memory descriptor and memory areas

每個虛擬內存區(qū)域(VMA)是一個連續(xù)的虛擬地址范圍;這些區(qū)域絕對不會重疊。一個 vmareastruct 的實例完整地描述了一個內存區(qū)域,包括它的起始和結束地址,flags 決定了訪問權限和行為,并且 vm_file 域指定了映射到這個區(qū)域的文件(如果有的話)。(除了內存映射段的例外情況之外,)一個 VMA 是不能匿名映射文件的。上面的每個內存段(比如,堆、棧)都對應一個單個的 VMA。雖然它通常都使用在 x86 的機器上,但它并不是必需的。VMA 也不關心它們在哪個段中。

一個程序的 VMA 在內存描述符中是作為 mmap 域的一個鏈接列表保存的,以起始虛擬地址為序進行排列,并且在 mm_rb 域中作為一個 紅黑樹 的根。紅黑樹允許內核通過給定的虛擬地址去快速搜索內存區(qū)域。在你讀取文件 /proc/pid_of_process/maps 時,內核只是簡單地讀取每個進程的 VMA 的鏈接列表并顯示它們

在 Windows 中,EPROCESS 塊大致類似于一個 taskstruct 和 mmstruct 的結合。在 Windows 中模擬一個 VMA 的是虛擬地址描述符,或稱為 VAD;它保存在一個 AVL 樹 中。你知道關于 Windows 和 Linux 之間最有趣的事情是什么嗎?其實它們只有一點小差別。

4GB 虛擬地址空間被分配到頁面中。在 32 位模式中的 x86 處理器中支持 4KB、2MB、以及 4MB 大小的頁面。Linux 和 Windows 都使用大小為 4KB 的頁面去映射用戶的一部分虛擬地址空間。字節(jié) 0-4095 在頁面 0 中,字節(jié) 4096-8191 在頁面 1 中,依次類推。VMA 的大小 必須是頁面大小的倍數 。下圖是使用 4KB 大小頁面的總數量為 3GB 的用戶空間:

4KB Pages Virtual User Space

4KB Pages Virtual User Space

處理器通過查看頁面表去轉換一個虛擬內存地址到一個真實的物理內存地址。每個進程都有它自己的一組頁面表;每當發(fā)生進程切換時,用戶空間的頁面表也同時切換。Linux 在內存描述符的 pgd 域中保存了一個指向進程的頁面表的指針。對于每個虛擬頁面,頁面表中都有一個相應的頁面表條目(PTE),在常規(guī)的 x86 頁面表中,它是一個簡單的如下所示的大小為 4 字節(jié)的記錄:

x86 Page Table Entry (PTE) for 4KB page

x86 Page Table Entry (PTE) for 4KB page

Linux 通過函數去 讀取 和 設置  PTE 條目中的每個標志位。標志位 P 告訴處理器這個虛擬頁面是否物理內存中。如果該位被清除(設置為 0),訪問這個頁面將觸發(fā)一個頁面故障。請記住,當這個標志位為 0 時,內核可以在剩余的域上做任何想做的事。R/W 標志位是讀/寫標志;如果被清除,這個頁面將變成只讀的。U/S 標志位表示用戶/超級用戶;如果被清除,這個頁面將僅被內核訪問。這些標志都是用于實現我們在前面看到的只讀內存和內核空間保護。

標志位 D 和 A 用于標識頁面是否是“臟的”或者是已被訪問過。一個臟頁面表示已經被寫入,而一個被訪問過的頁面則表示有一個寫入或者讀取發(fā)生過。這兩個標志位都是粘滯位:處理器只能設置它們,而清除則是由內核來完成的。最終,PTE 保存了這個頁面相應的起始物理地址,它們按 4KB 進行整齊排列。這個看起來不起眼的域是一些痛苦的根源,因為它限制了物理內存最大為 4 GB。其它的 PTE 域留到下次再講,因為它是涉及了物理地址擴展的知識。

由于在一個虛擬頁面上的所有字節(jié)都共享一個 U/S 和 R/W 標志位,所以內存保護的最小單元是一個虛擬頁面。但是,同一個物理內存可能被映射到不同的虛擬頁面,這樣就有可能會出現相同的物理內存出現不同的保護標志位的情況。請注意,在 PTE 中是看不到運行權限的。這就是為什么經典的 x86 頁面上允許代碼在棧上被執(zhí)行的原因,這樣會很容易導致挖掘出棧緩沖溢出漏洞(可能會通過使用 return-to-libc 和其它技術來找出非可執(zhí)行棧)。由于 PTE 缺少禁止運行標志位說明了一個更廣泛的事實:在 VMA 中的權限標志位有可能或可能不完全轉換為硬件保護。內核只能做它能做到的,但是,最終的架構限制了它能做的事情。

虛擬內存不保存任何東西,它只是簡單地  映射  一個程序的地址空間到底層的物理內存上。物理內存被當作一個稱之為物理地址空間的巨大塊而由處理器訪問。雖然內存的操作涉及到某些總線,我們在這里先忽略它,并假設物理地址范圍從 0 到可用的最大值按字節(jié)遞增。物理地址空間被內核進一步分解為頁面幀。處理器并不會關心幀的具體情況,這一點對內核也是至關重要的,因為,頁面幀是物理內存管理的最小單元。Linux 和 Windows 在 32 位模式下都使用 4KB 大小的頁面幀;下圖是一個有 2 GB 內存的機器的例子:

Physical Address Space

Physical Address Space

在 Linux 上每個頁面幀是被一個 描述符 和 幾個標志 來跟蹤的。通過這些描述符和標志,實現了對機器上整個物理內存的跟蹤;每個頁面幀的具體狀態(tài)是公開的。物理內存是通過使用 Buddy 內存分配 (LCTT 譯注:一種內存分配算法)技術來管理的,因此,如果一個頁面幀可以通過 Buddy 系統(tǒng)分配,那么它是未分配的(free)。一個被分配的頁面幀可以是匿名的、持有程序數據的、或者它可能處于頁面緩存中、持有數據保存在一個文件或者塊設備中。還有其它的異形頁面幀,但是這些異形頁面幀現在已經不怎么使用了。Windows 有一個類似的頁面幀號(Page Frame Number (PFN))數據庫去跟蹤物理內存。

我們把虛擬內存區(qū)域(VMA)、頁面表條目(PTE),以及頁面幀放在一起來理解它們是如何工作的。下面是一個用戶堆的示例:

Physical Address Space

Physical Address Space

藍色的矩形框表示在 VMA 范圍內的頁面,而箭頭表示頁面表條目映射頁面到頁面幀。一些缺少箭頭的虛擬頁面,表示它們對應的 PTE 的當前標志位被清除(置為 0)。這可能是因為這個頁面從來沒有被使用過,或者是它的內容已經被交換出去了。在這兩種情況下,即便這些頁面在 VMA 中,訪問它們也將導致產生一個頁面故障。對于這種 VMA 和頁面表的不一致的情況,看上去似乎很奇怪,但是這種情況卻經常發(fā)生。

一個 VMA 像一個在你的程序和內核之間的合約。你請求它做一些事情(分配內存、文件映射、等等),內核會回應“收到”,然后去創(chuàng)建或者更新相應的 VMA。 但是,它 并不立刻 去“兌現”對你的承諾,而是它會等待到發(fā)生一個頁面故障時才去 真正 做這個工作。內核是個“懶惰的家伙”、“不誠實的人渣”;這就是虛擬內存的基本原理。它適用于大多數的情況,有一些類似情況和有一些意外的情況,但是,它是規(guī)則是,VMA 記錄 約定的 內容,而 PTE 才反映這個“懶惰的內核”  真正做了什么。通過這兩種數據結構共同來管理程序的內存;它們共同來完成解決頁面故障、釋放內存、從內存中交換出數據、等等。下圖是內存分配的一個簡單案例:

Example of demand paging and memory allocation

Example of demand paging and memory allocation

當程序通過 brk() 系統(tǒng)調用來請求一些內存時,內核只是簡單地 更新 堆的 VMA 并給程序回復“已搞定”。而在這個時候并沒有真正地分配頁面幀,并且新的頁面也沒有映射到物理內存上。一旦程序嘗試去訪問這個頁面時,處理器將發(fā)生頁面故障,然后調用 dopagefault()。這個函數將使用 find_vma() 去  搜索 發(fā)生頁面故障的 VMA。如果找到了,然后在 VMA 上進行權限檢查以防范惡意訪問(讀取或者寫入)。如果沒有合適的 VMA,也沒有所嘗試訪問的內存的“合約”,將會給進程返回段故障。

找到了一個合適的 VMA,內核必須通過查找 PTE 的內容和 VMA 的類型去處理故障。在我們的案例中,PTE 顯示這個頁面是 不存在的。事實上,我們的 PTE 是全部空白的(全部都是 0),在 Linux 中這表示虛擬內存還沒有被映射。由于這是匿名 VMA,我們有一個完全的 RAM 事務,它必須被 doanonymouspage() 來處理,它分配頁面幀,并且用一個 PTE 去映射故障虛擬頁面到一個新分配的幀。

有時候,事情可能會有所不同。例如,對于被交換出內存的頁面的 PTE,在當前(Present)標志位上是 0,但它并不是空白的。而是在交換位置仍有頁面內容,它必須從磁盤上讀取并且通過 doswappage() 來加載到一個被稱為 major fault 的頁面幀上。

這是我們通過探查內核的用戶內存管理得出的前半部分的結論。在下一篇文章中,我們通過將文件加載到內存中,來構建一個完整的內存框架圖,以及對性能的影響。 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2023-03-31 08:16:53

Flutter優(yōu)化內存管理

2011-07-28 11:12:25

Cocoa 內存

2017-11-02 09:30:00

Linux內核開發(fā)2017版

2018-12-06 10:40:50

磁盤緩存內存

2020-03-03 13:37:23

SSH密鑰管理工具開源工具

2025-02-14 09:53:50

2022-09-26 11:30:40

MQTT協議客戶端協議

2018-08-23 16:51:40

Linux軟件倉庫包管理器

2019-09-27 09:40:06

ElvishShellLinux

2010-07-05 16:20:32

NetBEUI協議

2021-08-12 14:19:14

Slice數組類型內存

2025-01-06 08:00:09

2018-05-22 14:34:50

編譯Linux內核

2020-12-31 12:16:49

SAP云計算SAP產品

2021-02-03 16:22:43

新基建SAP

2021-05-31 14:22:56

物聯網物聯網安全

2010-09-02 16:59:35

資源預留協議

2021-12-10 10:29:07

在線客服系統(tǒng)

2019-11-05 10:18:04

RPM包RPMLinux

2011-08-01 11:37:41

iPhone Objective- 內存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 又爽又黄axxx片免费观看 | 日韩免费网 | 国产乱码精品一区二区三区中文 | 日韩中文一区二区三区 | 在线观看成人精品 | 暖暖日本在线视频 | 亚洲国产成人精品女人 | 日韩精品一区二区三区 | 一级毛片免费完整视频 | 国产精品免费播放 | 亚洲男女视频在线观看 | 自拍偷拍中文字幕 | 99视频入口 | 国产精品久久久久久福利一牛影视 | 日韩欧美亚洲 | 精品久久久久久 | 亚洲欧美bt| 日韩av在线免费 | 欧美一级在线观看 | 日日干日日色 | 亚洲一页 | 欧美三级在线 | 日日爱视频 | 久草院线| 欧美一级三级在线观看 | 91精品国产综合久久久久久漫画 | 免费高清av | 日本亚洲欧美 | 国产视频一区二区 | 97精品超碰一区二区三区 | 毛片网站在线观看视频 | 国产在线观看不卡一区二区三区 | 亚洲精品国产第一综合99久久 | 欧美久久大片 | 亚洲精品一区中文字幕乱码 | 成人在线观看免费视频 | 黄色一级特级片 | 亚洲欧美日韩一区二区 | 特黄色一级毛片 | 国产精品一区久久久 | 日操夜操 |