段表和頁表【轉】


轉自:http://www.cnblogs.com/worldisimple/articles/2447577.html

一、概述處理器(CPU

1.1 處理器位數

在intel處理器的X86系列中,包含8086和8088的16位處理器,以及從80386(即i386)開始的32位處理器,而如今又有X86-64架構的64位處理器。

那這些16位,32位和64位又有什么意義了?位數越高,處理器的尋址能力越強,則可以支持越大的物理內存。具體如下表(可見對於64位處理器的尋址范圍已經是非常之大):

處理器位數

可支持的物理內存大小

尋址范圍

16

2^16 = 64K

0x0000 ~ 0xffff

32

2^32 = 4G

0x00000000 ~ 0xffffffff

64

2^64

 

在平時安裝操作系統時候,經常會問是要裝32位系統還是64位系統?對於32位處理器,只能安裝32位的系統,不能安裝64位系統。對於64位處理,既能夠安裝32位的系統,也可以安裝64位的系統。在Linux下可以通過下面的方面查詢系統裝的是幾位的:

(1) 查看根目錄下是否有有lib64目錄。32位系統只有/lib一個目錄,64位的系統會有/lib64和/lib兩個目錄。

(2) 執行getconf LONG_BIT命令查看返回結果。32位的系統中long類型是4字節(32位),64位的系統中long類型已變成了8字節(64位)。

(3) 執行uname -i命令。32位的系統返回i386,64位的系統放回x86_64

(4) 執行file /bin/ls命令。

32位系統返回如下結果:

/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5,dynamically linked (uses shared libs), stripped

64位系統返回如下結果:

/bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9,dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

1.2 處理器的寄存器

寄存器是處理器的組成部分,是有限存貯容量的高速存貯部件,它們可用來暫存指令、數據和位址。寄存器的訪問速度在所有存儲階層(見下圖)是最快的。

在大學學習匯編時候,還用寄存器來寫匯編程序,現在也忘記差不多了,這邊就大致記錄一下處理器分別有哪些寄存器。

在8086中,所有的寄存器都是16位的。

在80386中,寄存器的發生的變化如下:

(1) 把16位的通用寄存器、指令指針寄存器以及標志寄存器擴充為32位的寄存器。

(2) 段寄存器仍然為16位,並增加2個16位的段寄存器。

寄存器的分類

32CPU寄存器

16CPU寄存器

主要用途

數據

寄存器

EAX

AX

乘、除運算,字的輸入輸出,中間結果的緩存

EBX

BX

存儲器指針

ECX

CX

串操作、循環控制的計數器

EDX

DX

字的乘、除運算,間接的輸入輸出

變址

寄存器

ESI

SI

存儲器指針、串指令中的源操作數指針

EDI

DI

存儲器指針、串指令中的目的操作數指針

變址

寄存器

EBP

BP

存儲器指針、存取堆棧的指針

ESP

SP

堆棧的棧頂指針

指令指針寄存器

EIP

IP

存放下一條將要執行指令的偏移量,偏移量加上當前代碼段的基地址,就形成了下一條指令的地址。

標志位寄存器

EFLAG

FLAG

 

段寄存器

CS

CS

代碼段寄存器

DS

DS

數據段寄存器

SS

SS

堆棧段寄存器

ES

ES

附加數據段寄存器

FS

-

32CPU新增加的附加數據段寄存器

GS

-

32CPU新增加的附加數據段寄存器

(3) 增加4個32位的控制寄存器(CR0、CR1、CR2 和CR3),在進程管理及虛擬內存管理中會涉及到CR0(其中有2位分別用於指示運行在實模式/保護模式和是否開啟分頁機制)、CR2以及CR3(是頁目錄基址寄存器,保存頁目錄表的物理地址)這幾個寄存器。

(4) 增加4個系統地址寄存器,具體如下:

全局描述符表寄存器GDTR(Global Descriptor Table Register),是48位寄存器,用來保存全局描述符表(GDT)的32位基地址和16位GDT的界限。

中斷描述符表寄存器IDTR(Interrupt Descriptor Table Register),是48位寄存器,用來保存中斷描述符表(IDT)的32位基地址和16位IDT的界限。

局部描述符表寄存器LDTR(Global Descriptor Table Register),是16位寄存器,保存局部描述符表LDT段的選擇符。

任務狀態寄存器TR(Task State Register)是16位寄存器,用於保存任務狀態段TSS段的16位選擇符。

(5) 增加8個32位調式寄存器DR0~DR7

(6) 增加2個32位測試寄存器TR6和TR7

 

二、內存管理

 

下面的內容主要依賴於80386的32位處理器的保護模式下。

2.1 內存地址

物理內存單元的實際地址即物理地址。32位的處理器尋址范圍為0x00000000 ~ 0xffffffff,支持4G的物理內存大小。

程序產生的段選擇符與段相關的偏移地址部分構成了邏輯地址。在實模式下,沒有分段或分頁機制,邏輯地址和物理地址是相等的,不需要地址轉換可以直接訪問物理內存。但是在保護模式下,邏輯地址需要轉換成物理地址,才能訪問物理內存。那么,這個時候需要處理器中的內存管理單元(MMU)將邏輯地址映射為物理地址,來進行地址轉換(如下圖)。

那么,MMU是怎么將邏輯地址轉換成物理地址?

MMU是一種硬件電路,它包含兩個部件,一個是分段部件,一個是分頁部件,通過分段機制(把一個邏輯地址轉換為線性地址,線性地址也是32位,其地址取值范圍為0x00000000~0xffffffff)和分頁機制(把一個線性地址轉換為物理地址),最終將邏輯地址映射為物理地址。如下圖:

2.2 分段機制

在操作系統原理關於分段的說明:段的分配時為了更好的滿足用戶,段的長度不固定,由用戶定義,每個段都有自己的地址空間(通過基址包含某物理內存的地址,和長度值來表示段的長度),表示一個地址需要給出段部分(選擇符)和偏移部分。如下圖,如果沒有分頁的話,那么圖中的線性地址也就是物理地址,這種方式對於段的離散分配就很容易導致碎片問題(進而使用分頁機制來提高內存利用率):

在Linux中,主要設置了:內核代碼段,內核數據段,用戶代碼段,用戶數據段。而且每個段的基地址對應線性地址都是為0,而且都可以使用4G的地址空間,相當與繞過了邏輯地址和線性地址的映射,從而完全利用了分頁機制。另外,分段中怎樣使用段寄存器可以參考:http://book.51cto.com/art/200812/103305.htm

2.3 分頁機制

通過使用分頁機制可以很好的提高內存利用率。分頁機制把一個線性地址轉換為物理地址。Linux下一個頁大小為4K,把線性地址(32位)和物理地址(32位,2^32=4G物理內存)都按照4K(2^12)頁大小來進行划分,那么,一共有4G/4K=1M的頁面,如果只是簡單的進行線性地址和物理地址一對一記錄映射的話,這樣在映射表建立的就會占用比較大的物理內存。這個時候就引入了頁表頁目錄表,地址轉換過程見下圖:

(1) 通過對32位線性地址划分:第31~22這10位(2^10=1024)定位頁目錄項,第21~12這10位定位頁表項,第11~0這12位(2^12=4K)為頁內偏移值。

(2) 對於頁目錄表,有1024個頁目錄項,每個頁目錄項(又含有1024個頁表項)指向下一級頁表的物理地址(32位=4個字節),那么一共需要1024*4(=4K)字節,即只要分配一頁就可以完全存放。

(3) 對於頁表,原理和頁目錄表一樣,那么一共需要1024(1024個頁目錄項)*1024(每個頁目錄項含有1024個頁表項)*4(=1M)字節。

(4) 對於頁目錄的物理地址,就存放在CR3寄存器中。

所以,這樣可以尋址1024*1024*4K=4G的物理內存。另外,在Linux的X86架構引入了3級頁表機制(包括了頁全局目錄、頁中間目錄和頁表)。

【參考】

1深入分析Linux內核源碼

2OReilly.Understanding.the.Linux.Kernel.3rd.Edition

3、PPT: http://www.docin.com/p-54896290.html

4http://www.ibm.com/developerworks/cn/linux/l-memmod/

-----------------------------------------------------------------

zzfrom: http://chenxu.yo2.cn/articles/linux_memory.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM