⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emm-ia32_2.htm

📁 编写自己的操作系统
💻 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>&nbsp;</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>]&nbsp; [</FONT><A 
href="driver.htm"><FONT 
size=3>Top</FONT></A><FONT size=3>]&nbsp; [</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>]&nbsp; [</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.&nbsp;Segment 
&amp; Page</FONT></STRONG></FONT></SPAN></SPAN></SPAN></FONT></SPAN></P></DIV>
<DIV class=Section1 
style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt">&nbsp;</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 &lt; 
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&gt;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>&nbsp;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&nbsp;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>&nbsp; 
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>&nbsp;&nbsp; 
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>&nbsp;&nbsp;&nbsp;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>&nbsp;</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>&nbsp;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>&nbsp;Paging</STRONG></FONT></SPAN></SPAN></SPAN></SPAN></P>
<P class=Section1 style="LAYOUT-GRID-CHAR: none; LAYOUT-GRID-LINE: 15.6pt" 
align=left>&nbsp;</P></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -