1. 程式人生 > >計算機原理學習(6)-- x86-32 CPU和記憶體管理之分頁管理

計算機原理學習(6)-- x86-32 CPU和記憶體管理之分頁管理

前言

上一篇我們瞭解了x86-16 CPU計算機的記憶體訪問方式,定址方式,以及基於MS-DOS的應用程式的記憶體佈局。這一篇會主要介紹32位處理器的記憶體訪問,記憶體管理以及應用程式的記憶體佈局。雖然目前64位CPU已經非常普及了,不過相對於32位的記憶體管理方式並沒有大的變化,而32位相對於16位卻有了極大的改變。

1.  IA-32 CPU

1985年10月。Intel推出了80386 CPU 用來取代之前x86-16位的架構,一直到現在差不多塊20年的時間裡,雖然處理的速度,製造工藝都在不斷提升,但x86-32的架構都沒有大的改變。一般我們說的IA-32, I386和x86-32是一個意思。

從80386開始,地址線變為了32位,和CPU暫存器以及運算單元位數一樣,最大定址範圍增加到4G。所以在也不會出現16位CPU時訪問記憶體出現的問題。另外80386處理器都可以支援虛擬儲存器,支援真實模式,保護模式和虛擬8086模式,支援多工。 而之後的CPU,主要的改進就在於:

  1. CPU內部整合DMA,計數器,定時器等;
  2. 製造工藝的提示,更多的電晶體,更快的速度
  3. 加入更多的指令集,如MMX,SSE,SSE2等
  4. 整合L1,L2,L3快取記憶體,減少外部匯流排的訪問
  5. 超執行緒,多核心提高CPU效率

但是在記憶體管理訪問,卻沒有太大的變化,所以我們後面介紹的內容基本上可以試用所有的x86-32 CPU而不用特意去區分那個型號的CPU。

1.1 16位CPU記憶體訪問的問題

前一篇我們已經比較詳細的瞭解了16位CPU的記憶體訪問技術,現在可以會頭想想他所存在的缺點,

  1. 單任務: 16位的CPU只支援單任務,也就是同時只有一個程式在執行,隨著計算機的發展,單任務的缺點在於體驗較差;
  2. 記憶體小: 前面我們知道,在執行程式時,會把程式全部載入到記憶體中,但是當程式大於記憶體時,程式就無法運行了;
  3. 地址不確定:每次程式裝載時分配的地址可能都不一樣,使得程式在編寫時處理轉跳等問題非常麻煩。
  4. 安全差: 因為對於記憶體訪問沒有太多的限制,所以應用程式很容易去修改作業系統以及BIOS和硬體對映的記憶體空間,導致系統崩潰;

而當80386引入多工的支援後,以前的記憶體管理方式已經不能滿足現狀的需求的了。於是我們需要新的記憶體管理方式來解決上面的問題:

  1. 地址空間:這個是對實體記憶體的一個抽象,就好像程序是對CPU的一個抽象。一個程序可用於定址的一套地址的集合,每個程序都有自己的地址空間,相互獨立,這就解決了安全問題。
  2. 交換:把程式全部載入到記憶體,當程序處於空閒時,把他移除記憶體,存放到硬碟上,然後載入其他程式。這樣使得每個程序可以使用更多的記憶體。
  3. 虛擬記憶體:在老的記憶體管理中,一次把程式載入到記憶體,而當程式過大時就無法正常運行了。而利用到計算機系統的區域性性和儲存分層,我們可以只加載一部分需要使用的程式碼和資料到記憶體,當訪問的內容不在記憶體時,和已經使用完的部分進行交換,這樣就能在小記憶體的機器上執行大的程式了。對於程式來說這是透明的,看起來自己好像使用了全部記憶體。而多個應用完全可以使用相同的虛擬地址。

1.2 IA-32 CPU的記憶體訪問

32位CPU中開始,因為地址線和計算單元同為32位,所以採用了一種全新的記憶體訪問方式,虛擬定址。也就是CPU發出的地址並不是真正的實體地址,而是需要轉換才能得到真實的實體地址。初看起來和16位計算機的分段記憶體訪問好像差不多。但本質卻不同。16位的分段訪問是為了解決地址線位數大於CPU位數的問題。而虛擬定址則是真正解決了上面提到的那些問題。  當然,Intel為了相容,仍舊支援16位的分段式記憶體訪問。

CPU在內部增加了一個MMU(Memory Management Unit)單元來管理記憶體地址的轉換。我們知道在16位時代,僅僅使用一個地址加法器來計算地址,而這裡MMU單元除了可以轉換地址,還能提供記憶體訪問控制。 比如作業系統固定使用一段記憶體地址,當程序請求訪問這一段地址時,MMU可以拒絕訪問以保證系統的穩定性。而MMU的翻譯過程則需要作業系統的支援。所以可見硬體和軟體在計算機發展過程中是密不可分的。後面會詳細介紹虛擬地址轉換的過程。這也是本文的重點。

1.3 IA-32 CPU工作模式

從80286開始為了相容8086引入了真實模式和保護模式。但是80386因為引入了對虛擬記憶體的支援,使得保護模式相對80286有了很大改變。而80286也受限於當時MS-DOS只能工作於真實模式,所以無法使用到保護模式。所以我們一般談到保護模式都是指386之後的32位保護模式。而CPU工作模式也和作業系統有關。

  • 真實模式: 實際就是8086的工作模式,可定址空間為1M,採用分段式記憶體訪問。程式可以直接訪問BIOS和硬體的記憶體對映,所以目前計算機在啟動時都是在真實模式下。
  • 保護模式: 80386以後因為引入了虛擬儲存器,所以能更好的保護作業系統和各個程序的記憶體, 它主要體現在4G可定址空間,採用段頁式虛擬記憶體訪問,支援多工。當計算機啟動後,BIOS把控制權交給作業系統,從真實模式切換到保護模式。
  • 虛擬8086模式:  主要是在保護模式下虛擬執行8086的真實模式,這並不是一個CPU的模式,本質還是工作在真實模式下,但可以實現多工。

我們平時會經常聽到真實模式和保護模式,我們現在可以瞭解到他們主要的區別就在於記憶體訪問的方式上,而CPU工作模式也離不開作業系統的支援。在DOS和Windows 1.X系統中,只支援真實模式;Windows3.0中,同時支援真實模式和保護模式;而到了Windows3.1,從上面微軟作業系統和Intel CPU的版本圖來看,當時主流已經是80386和80486了,所以移除了對真實模式的支援。

1.4 IA-32 CPU暫存器

1.4.1 通用暫存器

IA32的CPU主要包含了8個32位的通用暫存器,

  • EAX,EBX,ECX,EDX相對於16位的CPU來說擴充套件成了32為,當然為了相容16為CPU,低位的16位和8位暫存器可以被單獨使用。 
  • ESI,EDI兩個個變址暫存器升級到了32位,其低位的16位對應之前的SI,DI暫存器、
  • ESP,EBP2個指標暫存器同樣變為32位,其低位的16位對應之前的SP,BP暫存器。

在8086記憶體定址中有介紹,只有BX,BP,SI,DI可以用來存放基址和變址的地址,但是80386開始,以上8個暫存器都可以用來存放指標地址,所以更加的通用。

1.4.2 段暫存器

32位CPU為了保持對16位CPU的相容性,保留了4個16位段暫存器,CS,SS,DS,ES,同時增加了2個段暫存器FS,GS

  • CS,SS,DS,ES: 工作在真實模式時與16位CPU的段暫存器作用相同;工作在保護模式則不在存放段值,而是作為選擇子,在虛擬地址轉換時使用。
  • FS和GS是新增的附加資料段,通過把段地址存入這兩個暫存器可以實現自定義定址。

1.4.3 指令指標暫存器和標誌暫存器

EIP擴充套件到了32位,和資料線相同。 低16位作用和IP暫存器相同。在32位計算機中存放的是指令的虛擬地址,16位計算機中存放的是CS段內有效地址。EFLAGS暫存器同樣擴充套件到32位,具體含義我們這裡不做介紹。

1.4.4 新增的暫存器

另外我們也看到,在IA-32中也新增了一些暫存器,GDTR/IDTR/LDTR/TR。他們主要在CPU保護模式下需要用到的暫存器,具體使用在後面會介紹到。

  • GDTR是全域性描述附表暫存器,主要存放作業系統和各任務公用的描述符;
  • LDTR是區域性描述符表暫存器,主要存放各個任務的私有描述符;
  • IDTR指出了保護模式中斷向量表的起始地址和大小(2K,最多256箇中斷);
  • TR是任務暫存器;

2. 虛擬儲存器

虛擬儲存器我們一般也稱為虛擬記憶體(和Windows中的虛擬記憶體不是一個概念,但是有關聯),它的基本思想是:

  • 每個程序都有自己的地址空間;
  • 每個地址空間被分為多個塊,每個塊稱為頁,每個頁有連續的地址空間;
  • 這些頁被對映到實體記憶體,但不是所有也都在記憶體中程式才能執行;
  • 當使用的頁不在實體記憶體中時,由作業系統負責載入相應的頁;

在真實模式下,CPU將偏移地址和段暫存器,基址暫存器等進行計算得到的實際的實體地址。 而在保護模式下,引入了虛擬記憶體的概念,在虛擬記憶體中使用的地址稱為虛擬地址(線性地址),虛擬地址通過MMU將虛擬地址對映為實體地址,然後送到匯流排,進行記憶體訪問。這裡最關鍵的就是虛擬地址的對映。

2.1 分頁

對於虛擬記憶體來說,是對實體記憶體的抽象,整個虛擬記憶體空間被劃分成了多個大小固定的頁(page),每個頁連續的虛擬地址,組合成了一個完整的虛擬地址空間。同樣,作業系統也會把實體記憶體劃分為多個大小固定的塊,我們稱為頁框(page frame),它只是作業系統為了方便管理在邏輯上的劃分的一個數據結構,並不存放實際記憶體資料,但是我們可以簡單的認為它就是記憶體。這樣一個虛擬記憶體的page就可以和一個實體記憶體的page frame對應起來,產生對映關係。

 

關於一個虛擬頁的大小,現在的作業系統中一般是512B-64K(準確的說是地址範圍大小,而非容納資料的大小)。但是記憶體頁的大小會對系統性能產生影響,記憶體頁設得太小,記憶體頁會很多,管理記憶體頁的陣列會比較大,耗記憶體。記憶體頁設大了,因為一個程序擁有的記憶體是記憶體頁大小的整數倍,會導致碎片,即申請了很多記憶體,真正用到的只有一點。目前Windows和Linux上預設的記憶體頁面大小都是4K。

從上圖我們也可以看出,虛擬記憶體的頁和實體記憶體的頁框並不一定是一一對應的,虛擬記憶體的大小和系統的定址能力相關,也就是地址線的位數,而實體記憶體的頁框數取決於實際的記憶體大小。所以可能只有一部分頁有對應的頁框,而當訪問的資料不在實體記憶體中時就會出現缺頁,這個時候作業系統會負責調入新的頁,也就是建立新的對映。這樣就不需要一次把程式全部載入到記憶體。

2.1.1 虛擬頁是什麼?

很多人會有一個疑問,虛擬頁到底是實際存在的還是虛擬的?我們知道記憶體中存放的是執行檔案的程式碼和資料,而程式在執行前,它的資料和程式碼是存放在這個程式的可執行檔案中的(比如.exe和.so),而在執行時需要把可執行檔案載入到記憶體。所以我們把這個硬碟上的檔案也劃分為4K大小的頁(邏輯上劃分,實際是載入過程中載入器完成的),這就是虛擬頁裡面實際的東西。但是程式在執行是可能會申請記憶體,這個時候需要新的虛擬頁來對映,所以我們可以得知虛擬頁應該有3種狀態:

  1. 已對映:虛擬頁面被建立已經被載入到實體記憶體,和物理頁之間存在對映關係。
  2. 未對映:虛擬頁面被建立,但是沒有被載入到記憶體或已經被調出記憶體,和物理頁面之間沒有對映關係,當需要使用時調入記憶體建立對映。
  3. 未建立:虛擬頁面沒有被建立,可能是因為還沒有訪問到此頁面所以沒有載入或者是呼叫macllo來分配記憶體,只有在執行是才會被建立。

2.1.2 儲存器對映

載入應用程式到記憶體時,因為和虛擬地址有關,我們需要把應用程式檔案和虛擬記憶體關聯起來,在Linux中稱為儲存器對映,同時提供了一個mmap的系統呼叫來實現次功能。檔案被分成頁面大小的片,每一片包含一個虛擬頁面的內容,因為頁面排程程式是按需求排程,所以在這些虛擬頁面並沒有實際的進入記憶體,而是在CPU發出訪問請求時,會建立一個虛擬頁並載入到記憶體。我們在啟動一個程序時,載入器為我們完成了檔案對映的功能,所以此時我們的執行檔案又可以稱為映像檔案。實際上載入器並不真正負責從磁碟載入資料到記憶體,因為和虛擬記憶體建立了對映關係,所以這個操作是虛擬記憶體自動進行的。 正是有了儲存器對映的存在,使得我們可以很方便的將程式和資料載入到記憶體中。

2.1.3 交換分割槽

當CPU請求一個虛擬頁是,虛擬頁會被建立並載入到記憶體,而頁面排程演算法可能在頁面休眠或在記憶體滿的情況下更具排程演算法將虛擬頁交換出去,在適當的時候可能被交換回來。這個時候就需要一個區域來存放被交換出來的虛擬頁,這個區域稱為交換分割槽。 這個分割槽在Linux中稱為swap分割槽,而在Windows中我們稱為虛擬記憶體(注意這裡和我們談到的虛擬記憶體技術不是一回事)。

以前電腦記憶體很小,特別是玩一些遊戲時經常會提示記憶體不足,網上一般會告訴你增大你的虛擬記憶體(交換分割槽),這樣一來在記憶體不足的時候可以存放更多交換出來的虛擬頁,看起來好像記憶體變大了一樣。從這方面來說Windows把他叫虛擬記憶體(交換分割槽)也是很正確的。  交換分割槽雖然也是硬碟的一部分,但是交換分割槽沒有普通的檔案系統,這樣消除了將檔案偏移轉換為頁地址的開銷。但是過於頻繁的交換頁面,IO操作會導致系統性能下降。但是在記憶體不足時可以保證系統 正常執行。當然這也和交換分割槽的大小有關。

而如今,一般使用的電腦都已經4G,8G記憶體了,對於普通需求來說足夠大了。所以虛擬頁會長時間存在與記憶體中而不被交換出去。所以我們可以禁用掉交換分割槽,以便提高效能。對於Windwos 從Vista開始有一個Superfetch的記憶體管理機制,而linux有Preload與之類似。這種記憶體機制會將使用者經常用的應用的部分虛擬頁提前載入到記憶體,當用戶使用時就無需在從硬碟載入。而當應用休眠或關閉時,也不會將這些虛擬頁交換出去。

如下圖就是Windows 8上記憶體使用情況,其中最左灰色部分是給BIOS和硬體保留的記憶體對映區域;綠色為作業系統,驅動以及使用者程序使用的記憶體;橙色表示已經修改的記憶體也,當交換出來時需要先寫回到硬碟;而藍色部分5G記憶體則是用來快取了未啟用程序的資料和內碼表;最後剩餘的3M才是空閒記憶體。 當活動進行需要更多記憶體時會優先使用可用部分,當可用部分沒有記憶體可用時,會釋放一部分備用區域的記憶體。


 

2.2 頁表

上面我們看到當實際實體記憶體小於虛擬記憶體時,會存在缺頁以及頁面交換等問題。此時作業系統會處理這些事情,是的這一切對於程式來說是透明的,它們不知道發生了什麼,只知道自己可以使用全部的虛擬記憶體空間。而對於作業系統來說,它們需要負責一切,需要知道程式的那些頁在實際記憶體中,那些不在。於是出現了頁表,就是用來記錄虛擬記憶體的頁和物理頁框之間的對映關係。MMU也正是利用頁表來進行虛擬地址和實體地址的轉換。

上面這張圖是一張虛擬記憶體頁和實體記憶體頁框之間通過頁表的對映關係,其中虛擬頁面從VP0-VP7,物理頁為PP0-PP3,我們從圖中可以得到幾點資訊:

  1. 不是所有的虛擬記憶體頁都載入到了實體記憶體中(VP3,VP6未對映狀態);
  2. 不是所有虛擬記憶體頁都被建立(VP0,VP5未被建立)
  3. 所有的虛擬記憶體頁在頁表中都有一項紀錄,我們稱為PTE(Page Table Entry);
  4. 虛擬記憶體的頁是存放在磁碟上的;
  5. 頁表紀錄需要佔用記憶體空間;
  6. MMU通過頁表,將虛擬地址轉換為實體地址;

這裡可能會有疑問,為什麼VP5沒有被建立?虛擬頁不是應該連續的嗎?這就涉及到記憶體分段,程式編譯和載入一些列問題了,這個會在介紹程式載入時解釋。

最後我們看下頁表中PTE的結構,一個PTE大小是32位,系統在操作頁表時則會根據這些屬性進行相應操作。

  • P:存在標誌(1表示當前頁是載入到了實體記憶體中)
  • W:讀寫標誌(0時表示只讀)
  • U/S: 使用者/超級使用者(0時表示用超級使用者許可權)
  • PWT:連續寫入
  • PCD:禁用快取
  • A:訪問過
  • D:髒位(1表示被寫過)
  • PAT:頁面屬性索引表
  • G:全域性標誌(TLB中使用)
  • Avail:方便作業系統使用

2.3 虛擬地址轉換

通過上圖我們來分析一下虛擬地址轉換的過程:

  1. CPU送出要訪問的虛擬地址,地址的結構是【頁號+頁內地址】;
  2. 頁表存放在記憶體中,頁表的地址和長度資訊則存放在一個頁表專用的暫存器中;通過讀取暫存器的資訊獲得頁表的起始地址;
  3. 將虛擬地址的頁號與頁表其實地址相加可以得到頁表的實際地址
  4. 通過頁表的對映專案,可以得到對應的實體記憶體頁的號碼
  5. 通過物理頁號和業內偏移地址就能得到實際要訪問的實體地址

當然,如果訪問過程中出現缺頁,會產生一箇中斷,然後作業系統會載入需要的頁面並進行對映(設定頁表),最後返回物理頁號得到實體記憶體。從上面的過程我們可以知道,每次進行地址變化,MMU都要訪問記憶體。回憶8086地址變換時是不需要訪問記憶體的,於是虛擬地址的轉換會影響系統性能,但是相當於虛擬記憶體帶來的好處,這點代價還是值得的。

2.4 頁表分級

在IA-32平臺上,地址線為32位,所以最大的定址範圍是4G,那麼最多能夠支援使用4GB的記憶體(記憶體按位元組編碼)。那麼對於虛擬記憶體來說,它的地址範圍為4G(0x00000000 ~ 0xFFFFFFFF),而一個記憶體頁的大小是4K,那麼一個程式虛擬記憶體空間中有1048576個頁(實際上程序可訪問的虛擬地址範圍沒有4G,Linux是3G,Windows是2G或3G)。

從上面我們知道每個虛擬頁都會在頁表中有一個PTE,每個PTE為32位,那麼對於一個程序至少需要4MB的記憶體來維護自己的頁表;而一個系統中可能存在多個進行,僅僅維護頁表這一項就需要消耗比較多記憶體。但實際上很多PTE項並沒有對映到對應的物理頁,這就造成了浪費。

有人會說那我們就動態建立頁表,在對映時才增加這一項。但是從虛擬地址轉換我們可以看到,找到PTE是通過PT首地址+頁號得到的,所以頁表PTE必須是連續的,但我們又知道並不是所有的虛擬頁都會馬上被建立,在訪問是就會出現問題,比如VP0-VP8中的VP5沒有被建立,當訪問頁號是5時,就會錯誤的訪問到VP6。所以為了解決頁表佔用記憶體過多的問題,引入了分級頁表。注意分級頁表也需要CPU硬體提供支援。

2.4.1 二級頁表

上圖是Linux系統上二級頁表的示意圖。與一級頁表不同的是,多增加了一層目錄,虛擬地址的組成變為了【目錄地址+頁表地址+頁內偏移】。其中頁內偏移地址為12位,頁表(PGT)地址為10位,頁表目錄(PGD)地址為10位。因為總過是32位,他們表示的PTE的個數是不變的。同樣,PEG的每一個專案也有自己的結構。

二級頁表地址轉換的過程也很簡單:

  1. 首先從cr3暫存器中找到PGD的首地址;(cr3暫存器用來儲存PGD的地址)
  2. PGD首地址和目錄號進行計算得到頁表的首地址;
  3. 頁表的首地址和頁號進行計算得到物理頁的首地址;
  4. 頁內偏移和物理頁地址通過計算得到最終的實體地址;

現在談一談為什麼頁表分級可以解決記憶體問題。首先因為頁表需要連續的大的記憶體空間,通過引入目錄級,我們可以離散對連續大空間的需求,這樣,只有在同一個目錄下的頁表才需要連續的空間。另一方面,如果某個目錄下的頁表中沒有任何對映的記錄,那麼這一張頁表就不需要載入。因為其他頁表可以通過其他目錄項來獲得,而不會存在一級表中不載入頁表項導致訪問出錯的問題。但是同一個頁表中,如果只有一個PTE被使用,這張頁表也是需要被載入的。分級的方法同樣用到了程式的區域性性原理。

2.4.2 多級頁表

 

對於32位系統最多能使用4G記憶體,為了讓系統可以使用更多記憶體,加入了 實體地址擴充套件(Physical Address Extension,縮寫為PAE)功能,可以支援36位。在前面8086時候我們見過類似的技術來使用更多記憶體。這個時候2級頁表就無法滿足要求了,於是引入了三級頁表。其中增加了PMD中間目錄一級。


為了適應64位CPU,作業系統又引入了4級頁表。但是總體上來說他們工作原理都是相同的,這裡就不敘述工作工程了。但是要注意的是,分級頁表需要處理器的支援,對於只支援二級或三級頁表的CPU來說,核心中體系結構相關的程式碼必須通過空頁表對缺少的頁表進行模擬。因此,記憶體管理程式碼剩餘部分的實現是與CPU無關的。目前Windows 2000/XP使用的是二級頁表,而使用PAE時則使用的是三級頁表,對於64位作業系統則採用了四級頁表。Linux則使用了四級頁表。

2.4.3 倒排頁表

在64位作業系統中,因為有64位地址線,所以頁表的大小可能非常非常大,雖然分級頁表可以不必載入全部頁表,IA-32,IA64系統一般使用四級頁表來處理,而在PowerPC等體系中則使用倒排頁表來解決這個問題。與傳統頁表的區別: 使用頁框號而不是虛擬頁號來索引頁表項。因為不是X86體系中常用的方法,這裡就不相信介紹了。具體可以檢視《現代作業系統》P113

2.5 TLB快取

前面介紹虛擬地址轉換時說過,相對於8086上的地址轉換而言,這裡多了一次記憶體訪問查詢頁表的過程。我們知道記憶體速度比CPU慢很多,每次從記憶體取資料都要訪問2次記憶體,會使得系統性能下降。

為了解決這個問題,在MMU中包含了一個關於PTE的緩衝區TLB(Translation Lookaside Buffer ),TLB是一個暫存器,所以它執行的速度和CPU速度相同。TLB中每一行儲存了一個PTE,如上圖所示,每次在去頁表中查詢之前,可以先在TLB中進行查詢,如果命中則直接拿到物理頁地址,如果不命中則再次訪問記憶體。我們多次提到程式的區域性性,在這裡下一個要訪問的地址很可能和前一個是在同一個記憶體頁中,於是我們可以直接從暫存器中拿到實體記憶體頁號,而不需要在訪問記憶體,這樣大大提高的了系統的速度。

上圖是TLB的一個基本結構,對於多級頁表來說,TLB可以快取每一級的地址,所以同樣能起作用。因為區域性性原理,多級頁表的訪問速度並不比一級頁表差。關於TLB更詳細的內容,可以檢視《深入理解計算機系統》P607 - P619

2.6 程序排程和虛擬記憶體

我們知道在系統中,每個程序都有自己獨立的虛擬空間,於是每個程序都有一張屬於自己的內頁表。 而我們翻譯地址時,從cr3中取出頁表目錄的首地址。對於不同的程序,他們都使用同一個暫存器。於是在CPU排程程序的時候,虛擬的地址空間也需要切換。於是對於普通使用者程式需要做下面幾件事情:

  1. 儲存當前程序的頁表目錄地址,也就是儲存cr3中存放的地址到程序上下文中
  2. 清空TLB中快取的資料
  3. 排程新的程序到CPU,並設定cr3暫存器的值為頁表目錄的首地址

但是記憶體中除了使用者程式之外還存在作業系統自身佔用的記憶體。我們可以簡單的把作業系統看成一個超大的程序,他和其他普通程序一樣需要使用虛擬記憶體,需要使用到頁表。當然作為核心程式,它必須是有一些特權的,下一篇我們將會介紹虛擬記憶體的佈局。而對於核心而言不是存在程序排程的。因為所有的核心程序都是共享核心的虛擬地址空間,而我們一般都稱之為核心執行緒,而非程序。 當然對於Linux而言,沒有執行緒的概念,執行緒和程序唯一不同就是是否共享虛擬地址空間。一般來說核心程式碼是常駐在記憶體的,那麼核心會不會缺頁呢?

3 小結

這一篇文章主要介紹了IA-32上的虛擬記憶體管理,主要的核心就是虛擬記憶體分頁。這也是現代作業系統和計算機的核心部分。整個虛擬記憶體部分涉及的內容也非常廣,加上自己理解不深,很多東西就只能簡單介紹了。而且記憶體管理這一塊不同作業系統可能會有一些不同的,這裡我儘量避開這些差異,總體來說都是比較通用的。在下一篇將主要介紹虛擬記憶體中的分段管理。

參考: