欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Windows內存管理
Windows內存管理

本文主要內容:
1.基本概念:物理內存、虛擬內存;物理地址、虛擬地址、邏輯地址;頁(yè)目錄,頁(yè)表
2.Windows內存管理
3.CPU段式內存管理
4.CPU頁(yè)式內存管理
 
一、基本概念
1. 兩個(gè)內存概念
物理內存:人盡皆知,就是插在主板上的內存條。他是固定的,內存條的容量多大,物理內存就有多大(集成顯卡系統除外)。但是如果程序運行很多或者程序本身很大的話(huà),就會(huì )導致大量的物理內存占用,甚至導致物理內存消耗殆盡。
虛擬內存:簡(jiǎn)明的說(shuō),虛擬內存就是在硬盤(pán)上劃分一塊頁(yè)面文件,充當內存。當程序在運行時(shí),有一部分資源還沒(méi)有用上或者同時(shí)打開(kāi)幾個(gè)程序卻只操作其中一個(gè)程序時(shí),系統沒(méi)必要將程序所有的資源都塞在物理內存中,于是,系統將這些暫時(shí)不用的資源放在虛擬內存上,等到需要時(shí)在調出來(lái)用。
2.三個(gè)地址概念
物理地址(physical address):用于內存芯片級的單元尋址,與處理器和CPU連接的地址總線(xiàn)相對應。
——這個(gè)概念應該是這幾個(gè)概念中最好理解的一個(gè),但是值得一提的是,雖然可以直接把物理地址理解成插在機器上那根內存本身,把內存看成一個(gè)從0字節一直到 最大空量逐字節的編號的大數組,然后把這個(gè)數組叫做物理地址,但是事實(shí)上,這只是一個(gè)硬件提供給軟件的抽像,內存的尋址方式并不是這樣。所以,說(shuō)它是“與 地址總線(xiàn)相對應”,是更貼切一些,不過(guò)拋開(kāi)對物理內存尋址方式的考慮,直接把物理地址與物理的內存一一對應,也是可以接受的。也許錯誤的理解更利于形而上的抽像。
邏輯地址(logical address):是指由程序產(chǎn)生的與段相關(guān)的偏移地址部分。例如,你在進(jìn)行C語(yǔ)言指針編程中,可以讀取指針變量本身值(&操作),實(shí)際上這個(gè)值就是邏輯地址,它是相對于你當前進(jìn)程數據段的地址,不和絕對物理地址相干。只有在Intel實(shí)模式下,邏輯地址才和物理地址相等(因為實(shí)模式?jīng)]有分段或分頁(yè)機制,Cpu不進(jìn)行自動(dòng)地址轉換);邏輯也就是在Intel 保護模式下程序執行代碼段限長(cháng)內的偏移地址(假定代碼段、數據段如果完全一樣)。應用程序員僅需與邏輯地址打交道,而分段和分頁(yè)機制對您來(lái)說(shuō)是完全透明的,僅由系統編程人員涉及。應用程序員雖然自己可以直接操作內存,那也只能在操作系統給你分配的內存段操作。
Intel為了兼容,將遠古時(shí)代的段式內存管理方式保留了下來(lái)。邏輯地址指的是機器語(yǔ)言指令中,用來(lái)指定一個(gè)操作數或者是一條指令的地址。以上例,我們說(shuō)的連接器為A分配的0x08111111這個(gè)地址就是邏輯地址。
——不過(guò)不好意思,這樣說(shuō),好像又違背了Intel中段式管理中,對邏輯地址要求,“一個(gè)邏輯地址,是由一個(gè)段標識符加上一個(gè)指定段內相對地址的偏移量, 表示為 [段標識符:段內偏移量],也就是說(shuō),上例中那個(gè)0x08111111,應該表示為[A的代碼段標識符: 0x08111111],這樣,才完整一些”
線(xiàn)性地址(linear address)或也叫虛擬地址(virtual address)
跟邏輯地址類(lèi)似,它也是一個(gè)不真實(shí)的地址,如果邏輯地址是對應的硬件平臺段式管理轉換前地址的話(huà),那么線(xiàn)性地址則對應了硬件頁(yè)式內存的轉換前地址。
-------------------------------------------------------------
每個(gè)進(jìn)程都有4GB的虛擬地址空間
這4GB分3部分
(1)一部分映射物理內存
(2)一部分映射硬盤(pán)上的交換文件
(3)一部分什么也不做
程序中都是使用4GB的虛擬地址,訪(fǎng)問(wèn)物理內存需要使用物理地址,物理地址是放在尋址總線(xiàn)上的地址,以字節(8位)為單位。
-------------------------------------------------------------
CPU將一個(gè)虛擬內存空間中的地址轉換為物理地址,需要進(jìn)行兩步:首先將給定一個(gè)邏輯地址(其實(shí)是段內偏移量,這個(gè)一定要理解?。。。?,CPU要利用其段式內存管理單元,先將為個(gè)邏輯地址轉換成一個(gè)線(xiàn)程地址,再利用其頁(yè)式內存管理單元,轉換為最終物理地址。
這樣做兩次轉換,的確是非常麻煩而且沒(méi)有必要的,因為直接可以把線(xiàn)性地址抽像給進(jìn)程。之所以這樣冗余,Intel完全是為了兼容而已。
3.頁(yè)表、頁(yè)目錄概念
使用了分頁(yè)機制之后,4G的地址空間被分成了固定大小的頁(yè),每一頁(yè)或者被映射到物理內存,或者被映射到硬盤(pán)上的交換文件中,或者沒(méi)有映射任何東西。對于一般程序來(lái)說(shuō),4G的地址空間,只有一小部分映射了物理內存,大片大片的部分是沒(méi)有映射任何東西。物理內存也被分頁(yè),來(lái)映射地址空間。對于32bit的 Win2k,頁(yè)的大小是4K字節。CPU用來(lái)把虛擬地址轉換成物理地址的信息存放在叫做頁(yè)目錄和頁(yè)表的結構里。
物理內存分頁(yè),一個(gè)物理頁(yè)的大小為4K字節,第0個(gè)物理頁(yè)從物理地址 0x00000000 處開(kāi)始。由于頁(yè)的大小為4KB,就是0x1000字節,所以第1頁(yè)從物理地址 0x00001000處開(kāi)始。第2頁(yè)從物理地址0x00002000處開(kāi)始??梢钥吹接捎陧?yè)的大小是4KB,所以只需要32bit的地址中高20bit來(lái)尋址物理頁(yè)。
頁(yè)目錄:  一個(gè)頁(yè)目錄大小為4K字節,放在一個(gè)物理頁(yè)中。由1024個(gè)4字節的頁(yè)目錄項組成。頁(yè)目錄項的大小為4 個(gè)字節(32bit),所以一個(gè)頁(yè)目錄中有1024個(gè)頁(yè)目錄項。頁(yè)目錄中的每一項的內容(每項4個(gè)字節)高20bit用來(lái)放一個(gè)頁(yè)表(頁(yè)表放在一個(gè)物理頁(yè)中)的物理地址,低12bit放著(zhù)一些標志。
頁(yè)表:  一個(gè)頁(yè)表的大小為4K字節,放在一個(gè)物理頁(yè)中。由1024個(gè)4字節的頁(yè)表項組成。頁(yè)表項的大小為4個(gè)字節 (32bit),所以一個(gè)頁(yè)表中有1024個(gè)頁(yè)表項。頁(yè)表中的每一項的內容(每項4個(gè)字節,32bit)高20bit用來(lái)放一個(gè)物理頁(yè)的物理地址,低 12bit放著(zhù)一些標志。
對于x86系統,頁(yè)目錄的物理地址放在CPU的CR3寄存器中。
4. 虛擬地址轉換成物理地址
一個(gè)虛擬地址大小為4字節,其中包含找到物理地址的信息
虛擬地址分3部分
(1)31-22位(10位)是頁(yè)目錄中的索引
(2)21-12位(10位)是頁(yè)表中的索引
(2)11-0位(12位)是頁(yè)內偏移

轉換過(guò)程:
首先通過(guò)CR3找到頁(yè)目錄所在物理頁(yè)-》根據虛擬地址中的31-22找到該頁(yè)目錄項-》通過(guò)該頁(yè)目錄項找到該虛擬地址對應的頁(yè)表地址-》根據虛擬地址21-12找到物理頁(yè)的物理地址-》更具虛擬地址的11-0位作為偏移加上該物理頁(yè)的地址就找到了 該虛擬地址對應的物理地址
CPU把虛擬地址轉換成物理地址:一個(gè)虛擬地址,大小4個(gè)字節(32bit),包含著(zhù)找到物理地址的信息,分為3個(gè)部分:第22位到第31位這10位(最高10位)是頁(yè)目錄中的索引,第 12位到第21位這10位是頁(yè)表中的索引,第0位到第11位這12位(低12位)是頁(yè)內偏移。對于一個(gè)要轉換成物理地址的虛擬地址,CPU首先根據CR3 中的值,找到頁(yè)目錄所在的物理頁(yè)。然后根據虛擬地址的第22位到第31位這10位(最高的10bit)的值作為索引,找到相應的頁(yè)目錄項(PDE, page directory entry),頁(yè)目錄項中有這個(gè)虛擬地址所對應頁(yè)表的物理地址。有了頁(yè)表的物理地址,根據虛擬地址的第12位到第21位這10位的值作為索引,找到該頁(yè)表中相應的頁(yè)表項(PTE,page table entry),頁(yè)表項中就有這個(gè)虛擬地址所對應物理頁(yè)的物理地址。最后用虛擬地址的最低12位,也就是頁(yè)內偏移,加上這個(gè)物理頁(yè)的物理地址,就得到了該虛擬地址所對應的物理地址。
-------------------------------------------------------------
一個(gè)頁(yè)目錄有1024項,虛擬地址最高的10bit剛好可以索引1024項(2的10次方等于1024)。一個(gè)頁(yè)表也有1024項,虛擬地址中間部分的 10bit,剛好索引1024項。虛擬地址最低的12bit(2的12次方等于4096),作為頁(yè)內偏移,剛好可以索引4KB,也就是一個(gè)物理頁(yè)中的每個(gè)字節。
-------------------------------------------------------------
一個(gè)虛擬地址轉換成物理地址的計算過(guò)程就是,處理器通過(guò)CR3找到當前頁(yè)目錄所在物理頁(yè),取虛擬地址的高10bit,然后把這10bit右移2bit(因為每個(gè)頁(yè)目錄項4個(gè)字節長(cháng),右移2bit相當于乘4)得到在該頁(yè)中的地址,取出該地址處PDE(4個(gè)字節),就找到了該虛擬地址對應頁(yè)表所在物理頁(yè),取虛擬地址第12位到第21位這10位,然后把這10bit右移2bit(因為每個(gè)頁(yè)表項4個(gè)字節長(cháng),右移2bit相當于乘4)得到在該頁(yè)中的地址,取出該地址處的PTE(4個(gè)字節),就找到了該虛擬地址對應物理頁(yè)的地址,最后加上12bit的頁(yè)內偏移得到了物理地址。
-------------------------------------------------------------
32bit的一個(gè)指針,可以尋址范圍0x00000000-0xFFFFFFFF,4GB大小。也就是說(shuō)一個(gè)32bit的指針可以尋址整個(gè)4GB地址空間的每一個(gè)字節。一個(gè)頁(yè)表項負責4K的地址空間和物理內存的映射,一個(gè)頁(yè)表1024項,也就是負責1024*4k=4M的地址空間的映射。一個(gè)頁(yè)目錄項,對應一個(gè)頁(yè)表。一個(gè)頁(yè)目錄有1024項,也就對應著(zhù)1024個(gè)頁(yè)表,每個(gè)頁(yè)表負責4M地址空間的映射。1024個(gè)頁(yè)表負責1024*4M=4G的地址空間映射。一個(gè)進(jìn)程有一個(gè)頁(yè)目錄。所以以頁(yè)為單位,頁(yè)目錄和頁(yè)表可以保證4G的地址空間中的每頁(yè)和物理內存的映射。
-------------------------------------------------------------
每個(gè)進(jìn)程都有自己的4G地址空間,從0x00000000-0xFFFFFFFF。通過(guò)每個(gè)進(jìn)程自己的一套頁(yè)目錄和頁(yè)表來(lái)實(shí)現。由于每個(gè)進(jìn)程有自己的頁(yè)目錄和頁(yè)表,所以每個(gè)進(jìn)程的地址空間映射的物理內存是不一樣的。兩個(gè)進(jìn)程的同一個(gè)虛擬地址處(如果都有物理內存映射)的值一般是不同的,因為他們往往對應不同的物理頁(yè)。

4G地址空間中低2G,0x00000000-0x7FFFFFFF是用戶(hù)地址空間,4G地址空間中高2G,即0x80000000-0xFFFFFFFF 是系統地址空間。訪(fǎng)問(wèn)系統地址空間需要程序有ring0的權限。
 
二. windows內存原理
 
主要的內容如下:
1.概述
2.虛擬內存
3.物理內存
4.映射

1.概述:
windows中 我們一般編程時(shí)接觸的都是線(xiàn)性地址 也就是我們所說(shuō)的虛擬地址,然而很不幸在我不斷成長(cháng)的過(guò)程中發(fā)現原來(lái)線(xiàn)性地址是操作系統自己意淫出來(lái)的,根本就不是我們數據真實(shí)存在的地方.換句話(huà)說(shuō)我們在0x80000000(虛擬地址)的地方寫(xiě)入了"UESTC"這個(gè)字符串,但是我們這個(gè)字符串并不真實(shí)存在于物理地址的0x80000000這里.再說(shuō)了真實(shí)的物理地址是利用一段N長(cháng)的數組來(lái)定位的(額~看不懂這句話(huà)沒(méi)關(guān)系,一會(huì )看到物理地址那你就明白了).但是為什么windows乃至linux都需要采取這種方式來(lái)尋址呢?原因很簡(jiǎn)單 為了安全.聽(tīng)說(shuō)過(guò)保護模式吧?顧名思義就是這個(gè)模式下加入了保護系統安全的措施,同樣采用線(xiàn)性地址也是所謂的安全措施之一.
    我們假設下如果沒(méi)有使用線(xiàn)性地址,那么我們可以直接訪(fǎng)問(wèn)物理地址,但是這樣的話(huà)當我們往內存寫(xiě)東西的時(shí)候操作系統無(wú)法檢查這塊內存是否可寫(xiě),換句話(huà)說(shuō)操作系統無(wú)法實(shí)現對頁(yè)面訪(fǎng)問(wèn)控制.這點(diǎn)是很可怕的事情,就如win9x那樣沒(méi)事在應用態(tài)往內核地址寫(xiě)東西,還有沒(méi)有天理了~~
    由于操作系統的安全需要,催生了虛擬地址的應用.在CPU中有個(gè)叫MMU(應該是Memory Manage Unit 內存管理單元)的東西,專(zhuān)門(mén)負責線(xiàn)性地址和物理地址之間的轉化.我們每次讀寫(xiě)內存,從CPU的結構看來(lái)不是都要經(jīng)過(guò)ALU么,ALU拿到虛擬地址后扔給MMU轉化成物理地址后再把數據讀入寄存器中.過(guò)程就是如此.

2.虛擬內存
    我們編程時(shí)所面對的都是虛擬地址,對于每個(gè)進(jìn)程來(lái)說(shuō)都擁有4G的虛擬內存(小補充: 4G虛擬內存中,高2G內存屬于內核部分,是所有進(jìn)程共有的,低2G內存數據是進(jìn)程獨有的,每個(gè)進(jìn)程低2G內存都不一樣),但注意的是虛擬地址是操作系統自己意淫出來(lái)的,打個(gè)比方就是說(shuō)想法還未付諸實(shí)踐,所以不構成任何資源損失.比如我們要在0x80000000的地方寫(xiě)個(gè)"UESTC"的時(shí)候,操作系統就會(huì )將這個(gè)虛擬地址映射到一塊物理地址A中,你寫(xiě)這塊虛擬地址就相當于寫(xiě)物理地址A.但是加入我們只申請了一段1KB的虛擬內存空間,并未讀寫(xiě),系統是不會(huì )分配任何物理內存的,只有當虛擬內存要使用時(shí)系統才會(huì )分配相應的物理空間.
    下面要說(shuō)些細節點(diǎn)的了,其實(shí)說(shuō)白了虛擬內存的管理是由一堆數據結構來(lái)實(shí)現的,下面給出這些數據結構:
(懶得打那么多 就只打出重要的部分~~)
在EPROCESS中有個(gè)數據結構如下:
typedef struct _MADDRESS_SPACE
{
    PMEMORY_AREA MemoryAreaRoot ; //這個(gè)指針指向一顆二叉排序樹(shù),想必學(xué)過(guò)數據結構的朋友都曉得吧~~嘿嘿~~ 主要是這個(gè)情況下采用二叉排序樹(shù)能加快內存的搜索速度
    ...
    ...
    ...
}MADDRESS_SPACE , *PMADDRESS_SPACE ;

然而這顆二叉排序樹(shù)的節點(diǎn)結構結構是這樣的:
typedef struct _MEMORY_AREA
{
    PVOID StartingAddress ; //虛擬內存段的起始地址
    PVOID EndingAddress ;   //虛擬內存段的結束地址
    struct _MEMORY_AREA *Parent ; //該節點(diǎn)的老爹
    struct _MEMORY_AREA *LeftChild ; //該節點(diǎn)的左兒子
    struct _MEMORY_AREA *RrightChild ; //該節點(diǎn)的左兒子
    ...
    ...
    ...

}MEMORY_AREA , *PMEMORY_AREA ;
    這個(gè)節點(diǎn)內主要記錄了已分配的虛擬內存空間,如果要申請虛擬內存空間就跑來(lái)這里創(chuàng )建個(gè)節點(diǎn)就好了,如果要刪除空間同樣把對應節點(diǎn)刪除就好了.不過(guò)說(shuō)來(lái)簡(jiǎn)單,其實(shí)還會(huì )涉及到很多操作,比如要平衡這棵樹(shù)什么的.
    那么我們在分配虛擬內存空間時(shí)系統會(huì )跑去找到這顆樹(shù),然后通過(guò)一定算法遍歷這顆樹(shù),找到符合條件的內存空隙(未分配的內存空間),創(chuàng )建個(gè)節點(diǎn)掛到這顆樹(shù)上,返回起始地址就完成了.


3.物理內存
    接下來(lái)就到物理內存的東東了,其實(shí)呢 物理內存的管理是基于一個(gè)數組來(lái)管理的,聽(tīng)說(shuō)過(guò)分頁(yè)機制吧,下面說(shuō)下分頁(yè).windows下分頁(yè)是4kb一頁(yè) 那么假設我們物理內存有4GB 那么windows會(huì )將這4GB空間分頁(yè),分成4GB/4KB = 1M頁(yè)    那么每一頁(yè)(就是4KB)的物理空間都由一個(gè)叫PHYSICAL_PAGE的數據結構管理,這個(gè)數據結構就不寫(xiě)啦....一來(lái)我寫(xiě)的手酸 二來(lái)看的人也累~~說(shuō)說(shuō)思路就好了.
    接著(zhù)以上假設 4GB的內存 操作系統就會(huì )相應產(chǎn)生一個(gè)PHYSICAL_PAGE數組,這個(gè)數組有多少個(gè)元素呢?有1M個(gè) 正好覆蓋了4GB的物理地址.這就是所謂的分頁(yè)機制的原型.說(shuō)白了就是把內存按4k劃分來(lái)管理.那么物理地址就好定位了,所謂的物理內存地址就可以直接以數組下標來(lái)表示,其實(shí)這里的物理內存地址指的是物理內存地址的頁(yè)面號... 具體地址還是要根據虛擬內存地址的低12位和物理內存的頁(yè)面號一起確定的
     再說(shuō)下物理內存的管理吧,在內核下有3個(gè)隊列 這些隊列內的元素就是上邊所說(shuō)的PHYSICAL_PAGE結構
它們分別是:
A.已分配的內存隊列 :存放正被使用的內存
B.待清理的內存隊列 :存放已被釋放的內存,但是這些內存未被清理(清零)
C.空閑隊列 :存放可使用的空閑內存

系統管理流程如下:
1).每隔一段時(shí)間,系統會(huì )自動(dòng)從B隊列中提取隊列元素進(jìn)行清理,然后放入空閑隊列中.
2).每當釋放物理內存時(shí),系統會(huì )將要釋放的內存從A隊列提取出來(lái),放入B隊列中.
3).申請內存時(shí),系統將要分配的內存從C隊列中提取出來(lái),放入A隊列中

4.映射
    說(shuō)到映射得先從虛擬內存的32位地址說(shuō)起.在CPU中存在個(gè)CR3寄存器,里面存放著(zhù)每個(gè)進(jìn)程的頁(yè)目錄地址

我們可以把轉換過(guò)程分成幾步看
1.根據CR3(注:CR3中的值是物理地址)的值我們可以定位到當前進(jìn)程的頁(yè)目錄基址,然后通過(guò)虛擬地址的高10位做偏移量來(lái)獲得指定的PDE(Page Directory Entry),PDE內容有4字節,高20位部分用來(lái)做頁(yè)表基址,剩下的比特位用來(lái)實(shí)現權限控制之類(lèi)的東西了.系統只要檢測相應的比特位就可以實(shí)現內存的權限控制了.
2.通過(guò)PDE提供的基址加上虛擬內存的中10位(21-12)做偏移量就找到了頁(yè)表PTE(Page Table Entry)地址,然后PTE的高20位就是物理內存的基址了(其實(shí)就是那個(gè)PHYSICAL_PAGE數組的下標號....),剩下的比特位同樣用于訪(fǎng)問(wèn)控制之類(lèi)的.
3.通過(guò)虛擬內存的低12位加上PTE中高20位做基址就可以確定唯一的物理內存了.

  
三. CPU段式內存管理,邏輯地址如何轉換為線(xiàn)性地址
一個(gè)邏輯地址由兩部份組成,段標識符: 段內偏移量。段標識符是由一個(gè)16位長(cháng)的字段組成,稱(chēng)為段選擇符。其中前13位是一個(gè)索引號。后面3位包含一些硬件細節,如圖:

最后兩位涉及權限檢查,本貼中不包含。

索引號,或者直接理解成數組下標——那它總要對應一個(gè)數組吧,它又是什么東東的索引呢?這個(gè)東東就是“段描述符(segment descriptor)”,呵呵,段描述符具體地址描述了一個(gè)段(對于“段”這個(gè)字眼的理解,我是把它想像成,拿了一把刀,把虛擬內存,砍成若干的截—— 段)。這樣,很多個(gè)段描述符,就組了一個(gè)數組,叫“段描述符表”,這樣,可以通過(guò)段標識符的前13位,直接在段描述符表中找到一個(gè)具體的段描述符,這個(gè)描 述符就描述了一個(gè)段,我剛才對段的抽像不太準確,因為看看描述符里面究竟有什么東東——也就是它究竟是如何描述的,就理解段究竟有什么東東了,每一個(gè)段描 述符由8個(gè)字節組成,如下圖:

這些東東很復雜,雖然可以利用一個(gè)數據結構來(lái)定義它,不過(guò),我這里只關(guān)心一樣,就是Base字段,它描述了一個(gè)段的開(kāi)始位置的線(xiàn)性地址。

Intel設計的本意是,一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每個(gè)進(jìn)程自己的,就放在所謂的“局部段描述符表 (LDT)”中。那究竟什么時(shí)候該用GDT,什么時(shí)候該用LDT呢?這是由段選擇符中的T1字段表示的,=0,表示用GDT,=1表示用LDT。

GDT在內存中的地址和大小存放在CPU的gdtr控制寄存器中,而LDT則在ldtr寄存器中。

好多概念,像繞口令一樣。這張圖看起來(lái)要直觀(guān)些:

首先,給定一個(gè)完整的邏輯地址[段選擇符:段內偏移地址],
1、看段選擇符的T1=0還是1,知道當前要轉換是GDT中的段,還是LDT中的段,再根據相應寄存器,得到其地址和大小。我們就有了一個(gè)數組了。
2、拿出段選擇符中前13位,可以在這個(gè)數組中,查找到對應的段描述符,這樣,它了Base,即基地址就知道了。
3、把Base + offset,就是要轉換的線(xiàn)性地址了。

還是挺簡(jiǎn)單的,對于軟件來(lái)講,原則上就需要把硬件轉換所需的信息準備好,就可以讓硬件來(lái)完成這個(gè)轉換了。OK,來(lái)看看Linux怎么做的。

Linux的段式管理
Intel要求兩次轉換,這樣雖說(shuō)是兼容了,但是卻是很冗余,呵呵,沒(méi)辦法,硬件要求這樣做了,軟件就只能照辦,怎么著(zhù)也得形式主義一樣。
另一方面,其它某些硬件平臺,沒(méi)有二次轉換的概念,Linux也需要提供一個(gè)高層抽像,來(lái)提供一個(gè)統一的界面。所以,Linux的段式管理,事實(shí)上只是“哄騙”了一下硬件而已。

按照Intel的本意,全局的用GDT,每個(gè)進(jìn)程自己的用LDT——不過(guò)Linux則對所有的進(jìn)程都使用了相同的段來(lái)對指令和數據尋址。即用戶(hù)數據段,用 戶(hù)代碼段,對應的,內核中的是內核數據段和內核代碼段。這樣做沒(méi)有什么奇怪的,本來(lái)就是走形式嘛,像我們寫(xiě)年終總結一樣。
[Copy to clipboard] [ - ]
CODE:
#define GDT_ENTRY_DEFAULT_USER_CS 14
#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)

#define GDT_ENTRY_DEFAULT_USER_DS 15
#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)

#define GDT_ENTRY_KERNEL_BASE 12

#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0)
#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)

#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1)
#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
把其中的宏替換成數值,則為:
[Copy to clipboard] [ - ]
CODE:
#define __USER_CS 115        [00000000 1110   0   11]
#define __USER_DS 123        [00000000 1111   0   11]
#define __KERNEL_CS 96    [00000000 1100   0   00]
#define __KERNEL_DS 104 [00000000 1101   0   00]
方括號后是這四個(gè)段選擇符的16位二制表示,它們的索引號和T1字段值也可以算出來(lái)了
[Copy to clipboard] [ - ]
CODE:
__USER_CS              index= 14 T1=0
__USER_DS             index= 15 T1=0
__KERNEL_CS           index=   12   T1=0
__KERNEL_DS           index= 13 T1=0
T1均為0,則表示都使用了GDT,再來(lái)看初始化GDT的內容中相應的12-15項(arch/i386/head.S):
[Copy to clipboard] [ - ]
CODE:
.quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */

按照前面段描述符表中的描述,可以把它們展開(kāi),發(fā)現其16-31位全為0,即四個(gè)段的基地址全為0。
這樣,給定一個(gè)段內偏移地址,按照前面轉換公式,0 + 段內偏移,轉換為線(xiàn)性地址,可以得出重要的結論,“在Linux下,邏輯地址與線(xiàn)性地址總是一致(是一致,不是有些人說(shuō)的相同)的,即邏輯地址的偏移量字段的值與線(xiàn)性地址的值總是相同的。?。?!”
忽略了太多的細節,例如段的權限檢查。呵呵。
Linux中,絕大部份進(jìn)程并不例用LDT,除非使用Wine ,仿真Windows程序的時(shí)候。

四.CPU頁(yè)式內存管理

CPU的頁(yè)式內存管理單元,負責把一個(gè)線(xiàn)性地址,最終翻譯為一個(gè)物理地址。從管理和效率的角度出發(fā),線(xiàn)性地址被分為以固定長(cháng)度為單位的組,稱(chēng)為頁(yè) (page),例如一個(gè)32位的機器,線(xiàn)性地址最大可為4G,可以用4KB為一個(gè)頁(yè)來(lái)劃分,這頁(yè),整個(gè)線(xiàn)性地址就被劃分為一個(gè)tatol_page [2^20]的大數組,共有2的20個(gè)次方個(gè)頁(yè)。這個(gè)大數組我們稱(chēng)之為頁(yè)目錄。目錄中的每一個(gè)目錄項,就是一個(gè)地址——對應的頁(yè)的地址。
另一類(lèi)“頁(yè)”,我們稱(chēng)之為物理頁(yè),或者是頁(yè)框、頁(yè)楨的。是分頁(yè)單元把所有的物理內存也劃分為固定長(cháng)度的管理單位,它的長(cháng)度一般與內存頁(yè)是一一對應的。
這里注意到,這個(gè)total_page數組有2^20個(gè)成員,每個(gè)成員是一個(gè)地址(32位機,一個(gè)地址也就是4字節),那么要單單要表示這么一個(gè)數組,就要占去4MB的內存空間。為了節省空間,引入了一個(gè)二級管理模式的機器來(lái)組織分頁(yè)單元。文字描述太累,看圖直觀(guān)一些:

如上圖,
1、分頁(yè)單元中,頁(yè)目錄是唯一的,它的地址放在CPU的cr3寄存器中,是進(jìn)行地址轉換的開(kāi)始點(diǎn)。萬(wàn)里長(cháng)征就從此長(cháng)始了。
2、每一個(gè)活動(dòng)的進(jìn)程,因為都有其獨立的對應的虛似內存(頁(yè)目錄也是唯一的),那么它也對應了一個(gè)獨立的頁(yè)目錄地址?!\行一個(gè)進(jìn)程,需要將它的頁(yè)目錄地址放到cr3寄存器中,將別個(gè)的保存下來(lái)。
3、每一個(gè)32位的線(xiàn)性地址被劃分為三部份,面目錄索引(10位):頁(yè)表索引(10位):偏移(12位)
依據以下步驟進(jìn)行轉換:
1、從cr3中取出進(jìn)程的頁(yè)目錄地址(操作系統負責在調度進(jìn)程的時(shí)候,把這個(gè)地址裝入對應寄存器);
2、根據線(xiàn)性地址前十位,在數組中,找到對應的索引項,因為引入了二級管理模式,頁(yè)目錄中的項,不再是頁(yè)的地址,而是一個(gè)頁(yè)表的地址。(又引入了一個(gè)數組),頁(yè)的地址被放到頁(yè)表中去了。
3、根據線(xiàn)性地址的中間十位,在頁(yè)表(也是數組)中找到頁(yè)的起始地址;
4、將頁(yè)的起始地址與線(xiàn)性地址中最后12位相加,得到最終我們想要的葫蘆;

這個(gè)轉換過(guò)程,應該說(shuō)還是非常簡(jiǎn)單地。全部由硬件完成,雖然多了一道手續,但是節約了大量的內存,還是值得的。那么再簡(jiǎn)單地驗證一下:
1、這樣的二級模式是否仍能夠表示4G的地址;
頁(yè)目錄共有:2^10項,也就是說(shuō)有這么多個(gè)頁(yè)表
每個(gè)目表對應了:2^10頁(yè);
每個(gè)頁(yè)中可尋址:2^12個(gè)字節。
還是2^32 = 4GB

2、這樣的二級模式是否真的節約了空間;
也就是算一下頁(yè)目錄項和頁(yè)表項共占空間 (2^10 * 4 + 2 ^10 *4) = 8KB。哎,……怎么說(shuō)呢?。。。ㄕ娴臏p少了嗎?因該是增加了吧,(4 + 2^10 * 4 + 2 ^10 * 2 ^10 *4) = 4100KB+4Byte)

值得一提的是,雖然頁(yè)目錄和頁(yè)表中的項,都是4個(gè)字節,32位,但是它們都只用高20位,低12位屏蔽為0——把頁(yè)表的低12屏蔽為0,是很好理解的,因 為這樣,它剛好和一個(gè)頁(yè)面大小對應起來(lái),大家都成整數增加。計算起來(lái)就方便多了。但是,為什么同時(shí)也要把頁(yè)目錄低12位屏蔽掉呢?因為按同樣的道理,只要 屏蔽其低10位就可以了,不過(guò)我想,因為12>10,這樣,可以讓頁(yè)目錄和頁(yè)表使用相同的數據結構,方便。

本貼只介紹一般性轉換的原理,擴展分頁(yè)、頁(yè)的保護機制、PAE模式的分頁(yè)這些麻煩點(diǎn)的東東就不啰嗦了……可以參考其它專(zhuān)業(yè)書(shū)籍。
 
 
 
 Win32通過(guò)一個(gè)兩層的表結構來(lái)實(shí)現地址映射,因為每個(gè)進(jìn)程都擁有私有的4G的虛擬內存空間,相應的,每個(gè)進(jìn)程都有自己的層次表結構來(lái)實(shí)現其地址映射。
      第一層稱(chēng)為頁(yè)目錄,實(shí)際就是一個(gè)內存頁(yè),Win32的內存頁(yè)有4KB大小,這個(gè)內存頁(yè)以4個(gè)字節分為1024項,每一項稱(chēng)為“頁(yè)目錄項”(PDE);
      第二層稱(chēng)為頁(yè)表,這一層共有1024個(gè)頁(yè)表,頁(yè)表結構與頁(yè)目錄相似,每個(gè)頁(yè)表也都是一個(gè)內存頁(yè),這個(gè)內存頁(yè)以4KB的大小被分為1024項,頁(yè)表的每一項被稱(chēng)為頁(yè)表項(PTE),易知共有1024×1024個(gè)頁(yè)表項。每一個(gè)頁(yè)表項對應一個(gè)物理內存中的某一個(gè)“內存頁(yè)”,即共有1024×1024個(gè)物理內存頁(yè),每個(gè)物理內存頁(yè)為4KB,這樣就可以索引到4G大小的虛擬物理內存。
如下圖所示(注下圖中的頁(yè)目錄項和頁(yè)表項的大小應該是4個(gè)字節,而不是4kB):

      Win32提供了4GB大小的虛擬地址空間。因此每個(gè)虛擬地址都是一個(gè)32位的整數值,也就是我們平時(shí)所說(shuō)的指針,即指針的大小為4B。它由三部分組成,如下圖:

      這三個(gè)部分的第一部分,即前10位為頁(yè)目錄下標,用來(lái)尋址頁(yè)目錄項,頁(yè)目錄項剛好1024個(gè)。找到頁(yè)目錄項后,找對頁(yè)目錄項對應的的頁(yè)表。第二部分則是用來(lái)在頁(yè)表內尋址,用來(lái)找到頁(yè)表項,共有1024個(gè)頁(yè)表項,通過(guò)頁(yè)表項找到物理內存頁(yè)。第三部分用來(lái)在物理內存頁(yè)中找到對應的字節,一個(gè)頁(yè)的大小是4KB,12位剛好可以滿(mǎn)足尋址要求。
具體的例子:
假設一個(gè)線(xiàn)程正在訪(fǎng)問(wèn)一個(gè)指針(Win32的指針指的就是虛擬地址)指向的數據,此指針指為0x2A8E317F,下圖表示了這一個(gè)過(guò)程:

0x2A8E317F的二進(jìn)制寫(xiě)法為0010101010_0011100011_000101111111,為了方便我們把它分為三個(gè)部分。
首先按照0010101010尋址,找到頁(yè)目錄項。因為一個(gè)頁(yè)目錄項為4KB,那么先將0010101010左移兩位,001010101000(0x2A8),用此下標找到頁(yè)目錄項,然后根據此頁(yè)目錄項定位到下一層的某個(gè)頁(yè)表。
然后按照0011100011尋址,在上一步找到頁(yè)表中尋找頁(yè)表項。尋址方法與上述方法類(lèi)似。找到頁(yè)表項后,就可以找到對應的物理內存頁(yè)。
最后按照000101111111尋址,尋找頁(yè)內偏移。
      上面的假設的是此數據已在物理內存中,其實(shí)判斷訪(fǎng)問(wèn)的數據是否在內存中也是在地址映射過(guò)程中完成的。Win32系統總是假設數據已在物理內存中,并進(jìn)行地址映射。頁(yè)表項中有一位標志位,用來(lái)標識包含此數據的頁(yè)是否在物理內存中,如果在的話(huà),就直接做地址映射,否則,拋出缺頁(yè)中斷,此時(shí)頁(yè)表項也可標識包含此數據的頁(yè)是否在調頁(yè)文件中(外存),如果不在則訪(fǎng)問(wèn)違例,程序將會(huì )退出,如果在,頁(yè)表項會(huì )查出此數據頁(yè)在哪個(gè)調頁(yè)文件中,然后將此數據頁(yè)調入物理內存,再繼續進(jìn)行地址映射。為了實(shí)現每個(gè)進(jìn)程擁有私有4G的虛擬地址空間,也就是說(shuō)每個(gè)進(jìn)程都擁有自己的頁(yè)目錄和頁(yè)表結構,對不同進(jìn)程而言,即使是相同的指針(虛擬地址)被不同的進(jìn)程映射到的物理地址也是不同的,這也意味著(zhù)在進(jìn)程之間傳遞指針是沒(méi)有意義的。


Linux的頁(yè)式內存管理
原理上來(lái)講,Linux只需要為每個(gè)進(jìn)程分配好所需數據結構,放到內存中,然后在調度進(jìn)程的時(shí)候,切換寄存器cr3,剩下的就交給硬件來(lái)完成了(呵呵,事實(shí)上要復雜得多,不過(guò)偶只分析最基本的流程)。

前面說(shuō)了i386的二級頁(yè)管理架構,不過(guò)有些CPU,還有三級,甚至四級架構,Linux為了在更高層次提供抽像,為每個(gè)CPU提供統一的界面。提供了一個(gè)四層頁(yè)管理架構,來(lái)兼容這些二級、三級、四級管理架構的CPU。這四級分別為:

頁(yè)全局目錄PGD(對應剛才的頁(yè)目錄)
頁(yè)上級目錄PUD(新引進(jìn)的)
頁(yè)中間目錄PMD(也就新引進(jìn)的)
頁(yè)表PT(對應剛才的頁(yè)表)。

整個(gè)轉換依據硬件轉換原理,只是多了二次數組的索引罷了,如下圖:

那么,對于使用二級管理架構32位的硬件,現在又是四級轉換了,它們怎么能夠協(xié)調地工作起來(lái)呢?嗯,來(lái)看這種情況下,怎么來(lái)劃分線(xiàn)性地址吧!
從硬件的角度,32位地址被分成了三部份——也就是說(shuō),不管理軟件怎么做,最終落實(shí)到硬件,也只認識這三位老大。
從軟件的角度,由于多引入了兩部份,,也就是說(shuō),共有五部份?!尪蛹軜嫷挠布J識五部份也很容易,在地址劃分的時(shí)候,將頁(yè)上級目錄和頁(yè)中間目錄的長(cháng)度設置為0就可以了。
這樣,操作系統見(jiàn)到的是五部份,硬件還是按它死板的三部份劃分,也不會(huì )出錯,也就是說(shuō)大家共建了和諧計算機系統。

這樣,雖說(shuō)是多此一舉,但是考慮到64位地址,使用四層轉換架構的CPU,我們就不再把中間兩個(gè)設為0了,這樣,軟件與硬件再次和諧——抽像就是強大呀?。?!

例如,一個(gè)邏輯地址已經(jīng)被轉換成了線(xiàn)性地址,0x08147258,換成二制進(jìn),也就是:
0000100000 0101000111 001001011000
內核對這個(gè)地址進(jìn)行劃分
PGD = 0000100000
PUD = 0
PMD = 0
PT = 0101000111
offset = 001001011000

現在來(lái)理解Linux針對硬件的花招,因為硬件根本看不到所謂PUD,PMD,所以,本質(zhì)上要求PGD索引,直接就對應了PT的地址。而不是再到PUD和 PMD中去查數組(雖然它們兩個(gè)在線(xiàn)性地址中,長(cháng)度為0,2^0 =1,也就是說(shuō),它們都是有一個(gè)數組元素的數組),那么,內核如何合理安排地址呢?
從軟件的角度上來(lái)講,因為它的項只有一個(gè),32位,剛好可以存放與PGD中長(cháng)度一樣的地址指針。那么所謂先到PUD,到到PMD中做映射轉換,就變成了保 持原值不變,一一轉手就可以了。這樣,就實(shí)現了“邏輯上指向一個(gè)PUD,再指向一個(gè)PDM,但在物理上是直接指向相應的PT的這個(gè)抽像,因為硬件根本不知 道有PUD、PMD這個(gè)東西”。

然后交給硬件,硬件對這個(gè)地址進(jìn)行劃分,看到的是:
頁(yè)目錄 = 0000100000
PT = 0101000111
offset = 001001011000
嗯,先根據0000100000(32),在頁(yè)目錄數組中索引,找到其元素中的地址,取其高20位,找到頁(yè)表的地址,頁(yè)表的地址是由內核動(dòng)態(tài)分配的,接著(zhù),再加一個(gè)offset,就是最終的物理地址了。
 
 
五. 存儲方式
保護模式現代操作系統的基礎,理解他是我們要翻越的第一座山。保護模式是相對實(shí)模式而言的,他們是處理器的兩種工作方式。很久以前大家使用的dos就是運行在實(shí)模式下,而現在的windows操作系統則是運行在保護模式下。兩種運行模式有著(zhù)較大的不同,
實(shí)模式由于是由8086/8088發(fā)展而來(lái)因此他更像是一個(gè)運行單片機的簡(jiǎn)單模式,計算機啟動(dòng)后首先進(jìn)入的就是實(shí)模式,通過(guò)8086/8088只有20根地址線(xiàn)所以它的尋址范圍只有2的20次冪,即1M。內存的訪(fǎng)問(wèn)方式就是我們熟悉的seg:offset邏輯地址方式,例如我們給出地址邏輯地址它將在cpu內轉換為20的物理地址,即將seg左移4位再加上offset值。例如地址1000h:5678h,則物理地址為10000h+5678h=15678h。實(shí)模式在后續的cpu中被保留了下來(lái),但實(shí)模式的局限性是很明顯的,由于使用seg:offset邏輯地址只能訪(fǎng)問(wèn)1M多一點(diǎn)的內存空間,在擁有32根地址線(xiàn)的cpu中訪(fǎng)問(wèn)1M以上的空間則變得很困難。而且隨著(zhù)計算機的不斷發(fā)展實(shí)模式的工作方式越來(lái)越不能滿(mǎn)足計算機對資源(存儲資源和cpu資源等等)的管理,由此產(chǎn)生了新的管理方式——保護模式。
80386及以上的處理器功能要大大超過(guò)其先前的處理器,但只有在保護模式下,處理器才能發(fā)揮作用。在保護模式下,全部32根地址線(xiàn)有效,可尋址4G的物理地址空間;擴充的存儲分段機制和可選的存儲器分頁(yè)機制,不僅為存儲器共享和保護提供了硬件支持,而且為實(shí)現虛擬存儲器提供了硬件支持;支持多任務(wù);4個(gè)特權級和完善的特權級檢查機制,實(shí)現了數據的安全和保密。計算機啟動(dòng)后首先進(jìn)入的就是實(shí)模式,通過(guò)設置相應的寄存器才能進(jìn)入保護模式(以后介紹)。保護模式是一個(gè)整體的工作方式,但分步討論由淺入深更利于學(xué)習。

存儲方式主要體現在內存訪(fǎng)問(wèn)方式上,由于兼容和IA32框架的限制,保護模式在內存訪(fǎng)問(wèn)上延用了實(shí)模式下的seg:offset的形式(即:邏輯地址),其實(shí)seg:offset的形式在保護模式下只是一個(gè)軀殼,內部的存儲方式與實(shí)模式截然不同。在保護模式下邏輯地址并不是直接轉換為物理地址,而是將邏輯地址首先轉換為線(xiàn)性地址,再將線(xiàn)性地址轉換為物理地址。

線(xiàn)性地址是個(gè)新概念,但大家不要把它想的過(guò)于復雜,簡(jiǎn)單的說(shuō)他就是0000000h~ffffffffh(即0~4G)的線(xiàn)性結構,是32個(gè)bite位能表示的一段連續的地址,但他是一個(gè)概念上的地址,是個(gè)抽象的地址,并不存在在現實(shí)之中。線(xiàn)性地址地址主要是為分頁(yè)機制而產(chǎn)生的。處理器在得到邏輯地址后首先通過(guò)分段機制轉換為線(xiàn)性地址,線(xiàn)性地址再通過(guò)分頁(yè)機制轉換為物理地址最后讀取數據。
 
分段機制是必須的,分頁(yè)機制是可選的,當不使用分頁(yè)的時(shí)候線(xiàn)性地址將直接映射為物理地址,設立分頁(yè)機制的目的主要是為了實(shí)現虛擬存儲(分頁(yè)機制在后面介紹)。先來(lái)介紹一下分段機制,以下文字是介紹如何由邏輯地址轉換為線(xiàn)性地址。
分段機制在保護模式中是不能被繞過(guò)得,回到我們的seg:offset地址結構,在保護模式中seg有個(gè)新名字叫做“段選擇子”(seg..selector)。段選擇子、GDT、LDT構成了保護模式的存儲結構,GDT、LDT分別叫做全局描述符表和局部描述符表,描述符表是一個(gè)線(xiàn)性表(數組),表中存放的是描述符。
“描述符”是保護模式中的一個(gè)新概念,它是一個(gè)8字節的數據結構,它的作用主要是描述一個(gè)段(還有其他作用以后再說(shuō)),用描述表中記錄的段基址加上邏輯地址(sel:offset)的offset轉換成線(xiàn)性地址。描述符主要包括三部分:段基址(Base)、段限制(Limit)、段屬性(Attr)。一個(gè)任務(wù)會(huì )涉及多個(gè)段,每個(gè)段需要一個(gè)描述符來(lái)描述,為了便于組織管理,80386及以后處理器把描述符組織成表,即描述符表。在保護模式中存在三種描述符表 “全局描述符表”(GDT)、“局部描述符表”(LDT)和中斷描述符表(IDT)(IDT在以后討論)。
(1)全局描述符表GDT(Global Descriptor Table)在整個(gè)系統中,全局描述符表GDT只有一張,GDT可以被放在內存的任何位置,但CPU必須知道GDT的入口,也就是基地址放在哪里,Intel的設計者門(mén)提供了一個(gè)寄存器GDTR用來(lái)存放GDT的入口地址,程序員將GDT設定在內存中某個(gè)位置之后,可以通過(guò)LGDT指令將GDT的入口地址裝入此積存器,從此以后,CPU就根據此寄存器中的內容作為GDT的入口來(lái)訪(fǎng)問(wèn)GDT了。GDTR中存放的是GDT在內存中的基地址和其表長(cháng)界限。

(2)段選擇子(Selector)由GDTR訪(fǎng)問(wèn)全局描述符表是通過(guò)“段選擇子”(實(shí)模式下的段寄存器)來(lái)完成的,如圖三①步。段選擇子是一個(gè)16位的寄存器(同實(shí)模式下的段寄存器相同)

段選擇子包括三部分:描述符索引(index)、TI、請求特權級(RPL)。他的index(描述符索引)部分表示所需要的段的描述符在描述符表的位置,由這個(gè)位置再根據在GDTR中存儲的描述符表基址就可以找到相應的描述符(如圖三①步)。然后用描述符表中的段基址加上邏輯地址(SEL:OFFSET)的OFFSET就可以轉換成線(xiàn)性地址(如圖三②步),段選擇子中的TI值只有一位0或1,0代表選擇子是在GDT選擇,1代表選擇子是在LDT選擇。請求特權級(RPL)則代表選擇子的特權級,共有4個(gè)特權級(0級、1級、2級、3級)。例如給出邏輯地址:21h:12345678h轉換為線(xiàn)性地址
a. 選擇子SEL=21h=0000000000100 0 01b 他代表的意思是:選擇子的index=4即100b選擇GDT中的第4個(gè)描述符;TI=0代表選擇子是在GDT選擇;左后的01b代表特權級RPL=1
b. OFFSET=12345678h若此時(shí)GDT第四個(gè)描述符中描述的段基址(Base)為11111111h,則線(xiàn)性地址=11111111h+12345678h=23456789h
(3)局部描述符表LDT(Local Descriptor Table)局部描述符表可以有若干張,每個(gè)任務(wù)可以有一張。我們可以這樣理解GDT和LDT:GDT為一級描述符表,LDT為二級描述符表。如圖五

LDT和GDT從本質(zhì)上說(shuō)是相同的,只是LDT嵌套在GDT之中。LDTR記錄局部描述符表的起始位置,與GDTR不同LDTR的內容是一個(gè)段選擇子。由于LDT本身同樣是一段內存,也是一個(gè)段,所以它也有個(gè)描述符描述它,這個(gè)描述符就存儲在GDT中,對應這個(gè)表述符也會(huì )有一個(gè)選擇子,LDTR裝載的就是這樣一個(gè)選擇子。LDTR可以在程序中隨時(shí)改變,通過(guò)使用lldt指令。如圖五,如果裝載的是Selector 2則LDTR指向的是表LDT2。舉個(gè)例子:如果我們想在表LDT2中選擇第三個(gè)描述符所描述的段的地址12345678h。
1. 首先需要裝載LDTR使它指向LDT2 使用指令lldt將Select2裝載到LDTR
2. 通過(guò)邏輯地址(SEL:OFFSET)訪(fǎng)問(wèn)時(shí)SEL的index=3代表選擇第三個(gè)描述符;TI=1代表選擇子是在LDT選擇,此時(shí)LDTR指向的是LDT2,所以是在LDT2中選擇,此時(shí)的SEL值為1Ch(二進(jìn)制為11 1 00b)。OFFSET=12345678h。邏輯地址為1C:12345678h
3. 由SEL選擇出描述符,由描述符中的基址(Base)加上OFFSET可得到線(xiàn)性地址,例如基址是11111111h,則線(xiàn)性地址=11111111h+12345678h=23456789h
4. 此時(shí)若再想訪(fǎng)問(wèn)LDT1中的第三個(gè)描述符,只要使用lldt指令將選擇子Selector 1裝入再執行2、3兩步就可以了(因為此時(shí)LDTR又指向了LDT1)
由于每個(gè)進(jìn)程都有自己的一套程序段、數據段、堆棧段,有了局部描述符表則可以將每個(gè)進(jìn)程的程序段、數據段、堆棧段封裝在一起,只要改變LDTR就可以實(shí)現對不同進(jìn)程的段進(jìn)行訪(fǎng)問(wèn)。
存儲方式是保護模式的基礎,學(xué)習他主要注意與實(shí)模式下的存儲模式的對比,總的思想就是首先通過(guò)段選擇子在描述符表中找到相應段的描述符,根據描述符中的段基址首先確定段的位置,再通過(guò)OFFSET加上段基址計算出線(xiàn)性地址.

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
linux內核中 邏輯地址、虛擬地址、線(xiàn)性地址和物理地址大掃盲
linux 內存分頁(yè)機制
邏輯地址、線(xiàn)性地址、物理地址和虛擬地址 - Linux - ***林電子科技有限公司
Linux內存管理圖解
IA-32 地址空間和APIC
計算機內存地址轉換與分段
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久