日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Linux内存寻址

發布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux内存寻址 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.內存地址分類以及MMU介紹

對于程序員來說,可以簡單的把內存地址理解為一種訪問存儲單元的內容的一種方式。而對于80x86系列微處理器來說,我們需要區分三種地址:

(1)邏輯地址

這種地址通常使用在機器語言里用于指定操作數或機器指令的地址。該類地址在著名的80x86分段體系架構中得到了很好體現,因此DOS程序員和windows程序員都不得不把他們的程序分成一段一段的(如代碼段、數據段、堆棧段等等)。每一個邏輯地址都是由一個段(segment)和相對于段的實際起始地址的偏移地址(即offset 或 displacement)組成。

(2)線性地址(又稱虛擬地址

一個32位的無符號整數就可用于描述4GB(2的32次方=4G)的內存地址空間,相當于4,294,967,296個內存單元。線性地址通常用16進制表示,大小范圍為:0x00000000 ~0xffffffff。

(3)物理地址

該類地址用于尋址/訪問內存芯片里的存儲單元。它們對應于微處理器引腳到內存總線之間的電信號物理地址由一個32比特或38比特的無符號整數的16進制表示。

內存管理單元(MMU)可通過一個叫做段單元(segmentation unit)的硬件電路,將邏輯地址轉換成線性地址;接著,通過一個叫做頁單元(paging unit)的電路,再將線性地址轉換成物理地址。如下圖所示:

在有多個處理器的系統中,所有的CPU共享相同的內存。這就意味著,RAM芯片可能被相互獨立的CPU們并發的訪問。由于對RAM芯片的讀操作和寫操作都必須串行地執行,在總線和每個內存芯片之間添加了一個叫做內存仲裁器的硬件電路。這個電路的作用是:當RAM芯片處于空閑狀態(這里的空閑,當然是指沒有CPU在訪問它)時,授權給CPU訪問(俗稱“放行”);當RAM芯片正忙(已經有CPU在使用該芯片)時,延遲(暫時禁止,即暫時“閉門謝客”)其他CPU對其訪問。

甚至單處理器系統中,也會使用內存仲裁器。這是因為這些系統包括特殊的處理器------DMA控制器,它與CPU也存在并發操作的情況。當然,多處理器系統中的內存仲裁器電路更為復雜,因為它有更多的輸入端口。例如,雙核奔騰在每個芯片的入口維護了一個雙端口的仲裁器,并且要求兩個CPU在使用公用的總線時必須交換同步消息。從編程的角度看,仲裁器是隱而不見的,因為它是完全由硬件電路管理的。

?

二.邏輯地址到虛擬地址的轉換

1.段選擇符和分段寄存器

一個邏輯地址包括兩部分:段標識符 和 段內相對偏移地址。段標識符是一個被叫做段選擇符(selector)的16比特的域,而偏移地址是一個32比特的域。

為了方便快速檢索段選擇符,處理器提供了6個分段寄存器(segmentation register)來緩存段選擇符,它們是:cs,ss,ds,es,fs和gs. 雖然只有這6個寄存器,但程序可以復用同一個寄存器來實現不同的目的,只需要把該寄存器的內容保存到內存中,在隨后需要的時候可以恢復它的內容。需要注意的是,cs、ss、ds有專門的用途。請看下面介紹:

cs-----內存段寄存器,指向含有代碼指令的段;cs寄存器還有一個重要的功能:用于區分用戶模式和內核模式,它包含一個指定當前優先級別(CPL, current priviledge level)的的2比特的域。如果該域的值為0,表明優先級最高;如果該值為3,表明最低的優先級。 Linux只使用了0和3,用以區分內核模式和用戶模式。

ss-----堆棧段寄存器,指向包含當前程序棧的段;

ds-----數據段寄存器,指向包含靜態和全局數據的段。

其它三個,即es,fs和gs,都是通用分段寄存器,可以指向任意類型的段。

?

2.段描述符

每一個段都由一個8字節的段描述符來表示,它描述了段的特征。段描述符要么存儲在全局描述符表(GDT)里,要么存儲在本地描述符表(LDT)里.

通常只定義了一個GDT。然而,每個進程都允許有自己的LDT,如果進程需要額外創建除了GDT里描述的之外的段。主存里GDT的地址和大小都包含在gdtr控制寄存器中,而當前正在使用的LDT的地址和大小則包含在ldtr控制寄存器中。

BASE:段的第一個字節的線性地址。

G:如果為0,則段的大小用字節表示。

Limit:保存了段中最后一個存儲單元的偏移值,因此與segment的長度、大小是綁定在一起的。如果G為0,則LIMIT的大小范圍為1字節~1MB;反之, LIMIT大小范圍為4KB~4GB.

S:如果為0,表示為一個系統段(system segment);反之,為一個普通的數據段或代碼段。系統段里保存了關鍵的數據結構,如LDT.

Type:描述segment的類型。

DPL:描述符優先級別。主要用于對segment的訪問進行限制。

P:描述段是否在內存中存在的標記。

3.對段描述符的快速訪問的實現

我們知道,邏輯地址由一個16比特的段選擇符和一個32比特的偏移地址組成。同時,我們也知道,分段寄存器里只存儲了段選擇符。

我們先接著第一節繼續對段選擇符進行分析。它的格式如下所示:

Index:標記了GDT或LDT中段描述符的入口。由于段寄存器有8個字節長,它在GDT或LDT中的相對地址是這樣來計算的:13個bit之長(如上圖,比特3-15位)的index域值乘以8. 假設GDT位于0x00020000 (該值存放在gdtr控制寄存器中) 并且 段選擇符的index域值為2,那么相應的段描述符的地址是這么來計算的:

0x00020000 +(2 x8),0x00020010.

TI: table indicator。TI=0,表示段描述符位于GDT中;TI=1,表示段描述符位于LDT中。

RPL:Requestor Previlige Level請求者優先級。

為了加快邏輯地址到線性地址的轉換過程,80x86增加了一個不可編程的寄存器。

每當一個段選擇符被加載到分段寄存器中時,相應的段描述符也被從內存里加載到那個匹配的不可編程的CPU寄存器中。這樣,邏輯地址的轉換就不再需要訪問主內存中的GDT和LDT,而只需要訪問那個包含段描述符的不可編程的寄存器。只有在分段寄存器內容改變時,才需要訪問LDT或GDT。

3.分段單元實現邏輯地址到線性地址的轉換

我們知道,內存管理單元(MMU)可通過一個叫做分段單元(segmentation unit)的硬件電路,將邏輯地址轉換成線性地址;接著,通過一個叫做分頁單元(paging unit)的電路,再將線性地址轉換成物理地址。如下圖所示:

那么,這個分段單元是按照什么樣的流程完成自己的職責所在呢?

首先,它會檢查段選擇符的TI域,進而知道是哪個描述表存放了相應的段描述符。如果段描述符位于GDT,則分段單元從gdtr寄存器中讀取GDT的線性基地址;否則,分段單元從ldtr讀取LDT的線性基地址。

其次,根據上一步得到的線性基地址和段選擇符的index域,計算出段描述符的地址。計算方法可參考上節。

通過以上兩步,我們就可以定位到我們需要的段描述符。

最后,把邏輯地址的偏移與前面定位到的段描述符的線性地址BASE域相加,得到線性地址。這樣,整個邏輯地址到線性地址的轉換過程就成了

地址轉換的過程如下圖所示:

注意,本文中的線性地址跟虛擬地址是一個概念。

?

Smith先生版權所有,出處:http://blog.csdn.net/acs713/article/details/7950414

總結

以上是生活随笔為你收集整理的Linux内存寻址的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。