?? emm-ia32_2.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0053)http://www.huihoo.com/gnu_linux/own_os/emm-ia32_2.htm -->
<HTML><HEAD><TITLE></TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1106" name=GENERATOR></HEAD>
<BODY>
<DIV class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT
face="Times New Roman" size=6><SPAN style="mso-tab-count: 1"><STRONG>2.2 IA-32
Memory Management Mechanism</STRONG></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT
face="Times New Roman" size=6><SPAN style="mso-tab-count: 1"><FONT
size=3></FONT></SPAN></FONT></SPAN> </P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT
face="Times New Roman" size=6><SPAN style="mso-tab-count: 1"><FONT
size=3>[</FONT><A
href="index.htm"><FONT
size=3>Home</FONT></A><FONT size=3>] [</FONT><A
href="driver.htm"><FONT
size=3>Top</FONT></A><FONT size=3>] [</FONT><FONT size=3><A
href="emm-principle_1.htm"
tppabs="http://pagoda-ooos.51.net/os_book/emm/emm-principle_1.htm">Previous</A></FONT><FONT
size=3>] [</FONT><FONT size=3>Next</FONT><FONT
size=3>]</FONT></SPAN></FONT></SPAN><SPAN lang=EN-US><FONT
face="Times New Roman" size=5><SPAN style="mso-tab-count: 1"></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></P><STRONG>
<HR width="100%" SIZE=2>
</STRONG>
<P></P>
<P></P></SPAN></FONT></SPAN><SPAN lang=EN-US><FONT
face="Times New Roman TUR"><SPAN style="mso-tab-count: 1">
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman"><STRONG><FONT size=5>1. Segment
& Page</FONT></STRONG></FONT></SPAN></SPAN></SPAN></FONT></SPAN></P></DIV>
<DIV class=Section1
style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"> </DIV>
<DIV class=Section1
style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"><FONT
face="Courier New" size=2>在IA-32體系上,內存地址概念分為3種:邏輯地址,線性地址和物理地址。</FONT></DIV>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=center><IMG src="emm-ia32_2.files/mm.gif"
tppabs="http://pagoda-ooos.51.net/os_book/emm/ia-32/mm.GIF"></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>其中邏輯地址指的是我們熟悉的Segment:Offset模式的地址,在IA-32上,Segment通過Segment
Selector來引用一個Segment Descriptor,在Segment Descriptor中定義了Segment Base
Address,Segment Limit,以及用作段保護目的的Segment
Attribute。在IA-32上任意給出的地址都是一個邏輯地址,即任意一個地址都是通過Segment:Offset的方式給出的。這是段內存訪問模式的基本特點。所以我們在IA-32上,我們無法避免使用段模式,因為我們必須按照Segment:Offset的方式給出一個地址。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New" size=2>最終一個邏輯地址會通過Segment Base
Address+Offset的方式轉化為一個線性地址,線性地址空間是指一段連續的,不分段的,范圍為0到4GB的地址空間,一個線性地址就是線性地址空間的一個絕對地址。如果沒有頁模式,則一個線性地址就被直接映射為物理地址,二者是相同的。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>如果使用分頁,則可以將一個大的線性地址空間映射到相對小的物理地址空間。其原理就是我們上一節所討論的頁表映射方式。頁模式再IA-32上是可選的。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>我們在上一節內容中討論了在內存管理模式中,如果我們想實現有效的虛擬內存管理,以讓多個應用程序可以有效的使用有限的物理內存,我們需要使用Paging模式。而Paging模式實現的是線性空間到物理地址空間的映射。而在IA-32上,你無法直接操作線性空間,而只能給出邏輯地址,由IA-32的段機制將其轉化為線性地址。但由于絕大多數硬件平臺都不支持段模式,而支持Paging模式,所以為了讓我們的OS有更好的可移植性,我們需要去掉段模式而只適用Paging模式。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>但令人討厭的是,IA-32規定段模式是不可禁止的,你不可能繞過它直接給出線性空間地址,我們必須使用它。萬般無奈之中,我們意識到,如果我們通過設置段,可以訪問到全部4
GB線性空間,同時給出的邏輯地址中的Offset恰好等于線性空間地址,那么我們一旦裝載好Segment
Selector之后,任意時刻給出的地址總是等于被轉化后的線性地址的話,那么其效果和直接操作線性空間沒有什么不同。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New" size=2>辦法就是創建一個基地址為0,Segment Limit為4
GB的段,這時任意給出一個offset,則等式為0+offset=linear Address,也就是說offset=linear
Address,另外由于段機制規定offset <
4GB,所以offset的范圍為[0h,FFFFFFFFh],恰好是線形空間范圍,這一切正是我們想要的。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>由于IA-32段機制規定,必須為代碼段和數據段創建不同的段,所以我們必須分別為代碼段和數據段分別創建一個Base
Address為0,Segment
Limit為4GB的段描述符,另外,由于我們的OS要讓內核運行在特權級0,而用戶程序運行在特權級別3,根據IA-32的段保護機制,特權級別3的程序是無法引用特權級別為0的段描述符的(因為CPL>DPL),所以我們必須分別為內核和用戶程序分別創建其代碼段和數據段。這就意味著我們必須創建4個段描述符——特權級別0的代碼段,特權級別0的數據段,特權級別3的代碼段,特權級別3的數據段。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>如果我們這么定義段,段保護則失去了作用,因為這些段使用完全相同的線形空間,它們互相覆蓋。你可以設想,如果不使用Paging的話,線形空間直接被影射到物理空間,則你修改任何一個段的數據,都會同時修改其它段的數據,段機制所提供的通過Base
Address:Limit方式將線形空間分割,以讓段與段之間完全隔離,來實現段保護的方式在這種情況下根本就不存在了。那么這是不是意味著用戶可以隨意修改內核數據了?不要慌,我們之所以這么定義段,正是為了實現一個純的Paging,此時我們已經不需要任何來自于段的保護(如果它提供了對我們來講反而可能是個負擔,比如我們仍然不得不使用4個段描述符。對一個純粹的Paging而言,段機制的任何痕跡都是多余的),而Paging機制會提供給你所有你所需要的保護。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><STRONG><FONT face="Times New Roman" size=5>
<HR width="100%" SIZE=2>
</FONT></STRONG>
<P></P>
<P></P>
<P><STRONG><FONT face="Times New Roman" size=5></FONT></STRONG></P><SPAN
lang=EN-US><SPAN style="mso-tab-count: 1">
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=5><STRONG><FONT
face="Times New Roman TUR">2.</FONT> Page
Table</STRONG></FONT></SPAN></SPAN></P><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=3>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New" size=2>IA-32模式對應兩種頁大小,提供了2種頁表模式。對于4
KB頁,使用2級頁表;而4 MB則使用1級頁表。我們不討論4 MB的頁,只討論4 KB的頁表模式。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2>4KB頁的2級頁表模式與我們在上一節討論的相同,這里就不再贅述。我們下面來看一看Page-Directory Entry和Page-Table
Entry的格式。</FONT></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=center><IMG src="emm-ia32_2.files/pte.gif"
tppabs="http://pagoda-ooos.51.net/os_book/emm/ia-32/pte.GIF"></P>
<UL>
<LI><FONT face="Courier New" size=2>Present-用來說明當前Page-Directory Entry所指向的Page
Table,或當前Page-Table
Entry所指向的Page是否在物理內存中,如果在,則設置為1,否則設為0。在一個線性地址到物理地址的轉化過程中,如果對應的Page-Directory或Page
Table Entry的Present為0,則產生一個Page-Fault異常,相應的異常處理程序將對此異常進行處理,應該將相應的Page
Table或Page裝入物理內存。CPU不會對這個標志進行任何操作,完全靠OS來設置或清除。</FONT></LI></UL>
<P><FONT face="Courier New" size=2>如果CPU產生一個Page-Fault異常,OS
Kernel中的Page-Fault異常處理程序必須按順序做如下處理:</FONT></P>
<OL type=1>
<LI><FONT face="Courier New" size=2>如果需要的話,將引起異常的Page從磁盤中裝入物理內存。 </FONT>
<LI><FONT face="Courier New" size=2>將此Page基地址的高20-bit設置到相應的Page-Table
Entry或Page-Directory
Entry的高20-bit。然后將此Entry的Present標志設為1。至于其它標志,比如Dirty和Access等,或許也需要被設置。 </FONT>
<LI><FONT face="Courier New" size=2>Invalidate TLB中當前的Page-Table Entry。
</FONT>
<LI><FONT face="Courier New"
size=2>從Page-Fault異常處理程序中返回,重新執行引起異常的地址訪問指令。</FONT></LI></OL>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New" size=2>
Present位是實現請求頁虛擬內存算法的關鍵位,所有支持Paging的硬件平臺都肯定支持這個位。</FONT></P>
<UL>
<LI><FONT face="Courier New" size=2>Read/Write(R/W)-用來指定一個頁(PTE)
或一組頁(PDE)是Read-Only的還是Read-Write的,一般將代碼頁設為Read-Only的,將數據頁設為Read-Write的,但在進程fork的時候,也會將數據頁設為Read-Only的,以實現Copy-On-Write技術。如果這個位被設置,則表示是Read-Write的,如果被清零,則表示是Read-Only的。</FONT></LI></UL>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New" size=2>
Read/Write域是頁保護機制的關鍵位之一,所有支持Paging的硬件平臺都肯定支持這個位。</FONT></P>
<UL>
<LI><FONT face="Courier New" size=2>User/Supervisor(U/S)-用來指定一個頁(PTE)
或一組頁(PDE)的訪問權限。一般將OS
Kernel的數據和代碼設置為Supervisor權限,將用戶進程的數據和代碼設置為User權限。如果這個位被設置,則表示此頁(PDE),或此組頁(PTE)是User權限,CPL位任何值都可以訪問這些頁;如果被清零,則表示此頁(PDE),或此組頁(PTE)是Supervisor權限,只有CPL=0,1,2時才能訪問這些頁,CPL=3時,訪問這些頁會引起Page-Fault異常。</FONT></LI></UL>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><FONT face="Courier New"
size=2> User/Supervisor位是頁保護機制的關鍵位之一,所有支持Paging的硬件平臺都肯定支持這個位。</FONT></P>
<UL>
<LI><FONT face="Courier New" size=2>Page-level Write
Through(PWT)-用于控制對單個Page,或者單個Page
Table的Write-through或write-back緩沖策略。如果PWT位被設置,則Write-through緩沖策略被使用。否則,Write-back緩沖策略被使用。如果CR0寄存器的CD(Cache-Disable)位被設置,則PWT的值被忽略,因為此時整個分頁系統緩沖已經被禁止,已經談不上什么緩沖策略了。</FONT></LI></UL>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left><BR> </P></FONT></SPAN></SPAN></SPAN></SPAN><STRONG><FONT
face="Times New Roman" size=5>
<HR width="100%" SIZE=2>
<P></P></FONT></STRONG>
<P></P>
<P><STRONG><FONT face="Times New Roman" size=5></FONT></STRONG></P><SPAN
lang=EN-US><SPAN style="mso-tab-count: 1">
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=5><STRONG><FONT
face="Times New Roman TUR">3.</FONT> Enable</STRONG></FONT></SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman"
size=5><STRONG> Paging</STRONG></FONT></SPAN></SPAN></SPAN></SPAN></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt"
align=left> </P></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -