用於記憶體晶元級的單元定址,與處理器和cpu連線的位址匯流排相對應。
雖然可以直接把實體地址理解成插在機器上那根記憶體本身,把記憶體看成乙個從0位元組一直到最大空量逐字節的編號的大陣列,然後把這個陣列叫做實體地址,但是事實上,這只是乙個硬體提供給軟體的抽像,記憶體的定址方式並不是這樣。所以,說它是「與位址匯流排相對應」,是更貼切一些,不過拋開對物理記憶體定址方式的考慮,直接把實體地址與物理的記憶體一一對應,也是可以接受的。也許錯誤的理解更利於形而上的抽像。
這是對整個記憶體(不要與機器上插那條對上號)的抽像描述。它是相對於物理記憶體來講的,可以直接理解成「不直實的」,「假的」記憶體,例如,乙個0x08000000記憶體位址,它並不對就實體地址上那個大陣列中0x08000000 - 1那個位址元素;
之所以是這樣,是因為現代作業系統都提供了一種記憶體管理的抽像,即虛擬記憶體(virtual memory)。程序使用虛擬記憶體中的位址,由作業系統協助相關硬體,把它「轉換」成真正的實體地址。這個「轉換」,是所有問題討論的關鍵。
有了這樣的抽像,乙個程式,就可以使用比真實實體地址大得多的位址空間。甚至多個程序可以使用相同的位址。不奇怪,因為轉換後的實體地址並非相同的。
——可以把連線後的程式反編譯看一下,發現聯結器已經為程式分配了乙個位址,例如,要呼叫某個函式a,**不是call a,而是call 0x0811111111 ,也就是說,函式a的位址已經被定下來了。沒有這樣的「轉換」,沒有虛擬位址的概念,這樣做是根本行不通的。
intel為了相容,將遠古時代的段式記憶體管理方式保留了下來。邏輯位址指的是機器語言指令中,用來指定乙個運算元或者是一條指令的位址。以上例,我們說的聯結器為a分配的0x08111111這個位址就是邏輯位址。
——不過不好意思,這樣說,好像又違背了intel中段式管理中,對邏輯位址要求,「乙個邏輯位址,是由乙個段識別符號加上乙個指定段內相對位址的偏移量,表示為 [段識別符號:段內偏移量],也就是說,上例中那個0x08111111,應該表示為[a的**段識別符號: 0x08111111],這樣,才完整一些」
跟邏輯位址類似,它也是乙個不真實的位址,如果邏輯位址是對應的硬體平台段式管理轉換前位址的話,那麼線性位址則對應了硬體頁式記憶體的轉換前位址。
cpu要利用其段式記憶體管理單元,先將為個邏輯位址轉換成乙個執行緒位址。
段識別符號是由乙個16位長的字段組成,稱為段選擇符。其中前13位是乙個索引號。後面3位包含一些硬體細節,如圖:
通過段識別符號中的索引號從gdt或者ldt找到該段的段描述符,段描述符中的base欄位是段的起始位址
一些全域性的段描述符,就放在「全域性段描述符表(gdt)」中,一些區域性的,例如每個程序自己的,就放在所謂的「區域性段描述符表(ldt)」中。
gdt在記憶體中的位址和大小存放在cpu的gdtr控制暫存器中,而ldt則在ldtr暫存器中。
段起始位址+ 段內偏移量 = 線性位址
1、看段選擇符的t1=0還是1,知道當前要轉換是gdt中的段,還是ldt中的段,再根據相應暫存器,得到其位址和大小。我們就有了乙個陣列了。
2、拿出段選擇符中前13位,可以在這個陣列中,查詢到對應的段描述符,這樣,它了base,即基位址就知道了。
3、把base + offset,就是要轉換的線性位址了。
再利用其頁式記憶體管理單元,轉換為最終實體地址。
linux假的段式管理
intel要求兩次轉換,這樣雖說是相容了,但是卻是很冗餘,但是這是intel硬體的要求。
其它某些硬體平台,沒有二次轉換的概念,linux也需要提供乙個高層抽像,來提供乙個統一的介面。
所以,linux的段式管理,事實上只是「哄騙」了一下硬體而已。
按照intel的本意,全域性的用gdt,每個程序自己的用ldt——不過linux則對所有的程序都使用了相同的段來對指令和資料定址。即使用者資料段,使用者**段,對應的,核心中的是核心資料段和核心**段。
在linux下,邏輯位址與線性位址總是一致的,即邏輯位址的偏移量欄位的值與線性位址的值總是相同的。
linux頁式管理
cpu的頁式記憶體管理單元,負責把乙個線性位址,最終翻譯為乙個實體地址。
線性位址被分為以固定長度為單位的組,稱為頁(page),例如乙個32位的機器,線性位址最大可為4g,可以用4kb為乙個頁來劃分,這頁,整個線性位址就被劃分為乙個tatol_page[2^20]的大陣列,共有2的20個次方個頁。
另一類「頁」,我們稱之為物理頁,或者是頁框、頁楨的。是分頁單元把所有的物理記憶體也劃分為固定長度的管理單位,它的長度一般與記憶體頁是一一對應的。
每個程序都有自己的頁目錄,當程序處於執行態的時候,其頁目錄位址存放在cr3暫存器中。
依據以下步驟進行轉換:
從cr3中取出程序的頁目錄位址(作業系統負責在排程程序的時候,把這個位址裝入對應暫存器);
根據線性位址前十位,在陣列中,找到對應的索引項,因為引入了二級管理模式,頁目錄中的項,不再是頁的位址,而是乙個頁表的位址。(又引入了乙個陣列),頁的位址被放到頁表中去了。
根據線性位址的中間十位,在頁表(也是陣列)中找到頁的起始位址;
將頁的起始位址與線性位址中最後12位相加。
目的:記憶體節約:如果一級頁表中的乙個頁表條目為空,那麼那所指的二級頁表就根本不會存在。這表現出一種巨大的潛在節約,因為對於乙個典型的程式,4gb虛擬位址空間的大部份都會是未分配的;
32位,pgd = 10bit,pud = pmd = 0,table = 10bit,offset = 12bit
64位,pud和pmd ≠ 0
實體地址和邏輯位址(虛擬位址)
1.實體地址 實體地址是載入到記憶體位址暫存器中的位址,是指記憶體中各物理儲存單元的位址從統一的基位址進行的順序編址。又稱絕對位址,它是資料在記憶體單元的真正位址。在前端匯流排上傳輸的記憶體位址都是物理記憶體位址,編號從0開始一直到可用物理記憶體的最高端。這些數字被北橋 nortbridge chi...
實體地址 虛擬位址 邏輯位址 線性位址
實際計算機的物理記憶體的位址,為32位或者64位。常見的記憶體條就是一類ram 隨機儲存儲存器,特點就是加電狀態下可任意讀寫,斷電後資訊消失 現代os都提供一技術 虛擬記憶體 virtual memory 它可以使給使用者錯覺好像自己在使用比實際物理記憶體大得多的記憶體,實際上通過對映把虛擬記憶體的...
邏輯位址,虛擬位址,實體地址,匯流排位址
很多人可能寫程式這麼多年,都分不清以下幾個位址的概念,亦或是當進入程式設計師行列時由於平台的關係有些概念已經漸漸弱化,沒有趕上那個必須與硬體親密接觸才能夠寫好程式的年代,所以平時也不會接觸到這些概念,但了解這些概念無疑是對程式設計生涯是有好處的,下面就簡述一下這幾個概念的意思。匯流排上的值。包機上,...