內核第二講,內存保護的實現,以及知識簡介,局部描述符,全局描述符.
一丶了解80386的各種模式
80386,也就是32位系統下,有三種模式需要了解一下.
實模式,保護模式.虛擬86模式
實模式: 指的是操作系統在啟動的是否,這時候訪問的內存都是實際的物理內存.而在這個是否,操作系統會填寫內核中的內中表格.比如今天講的表(全局描述符表 GDT)
保護模式: 當各種表填寫好了,那么我們的內存也被保護了.這個是否我們的進程就不會直接訪問物理地址了.進而產生了保護行為,我們的內存就有了 可讀 可寫,可執行一說了.
虛擬86模式: 操作系統啟動的是否,運行的都是實際的16位匯編.那么現在我們假設有一個16位程序要啟動.那么修改了我們物理地址的內存,那么保護模式不就沒用了.所以為了防止這一情況的產生,操作系統做了一個虛擬86模式,也就是說可以運行16位匯編程序.
關於更詳細的介紹,請下載當講課堂資料的 "8086處理器的工作模式.doc"文件進行查看.
二丶保護模式如何保護內存的.
我們通過上面模式的介紹,知道的操作系統啟動的是否會從實模式啟動,然后會切換到保護模式.
那么是如何保護內存的.
比如我們要保護 100地址的內存,讓其支持可以讀,不可以寫.那么在 ring3下有匯編代碼
mov [100],10
如何保證它不被改寫.
思路一:
操作系統作者進行各種判斷,判斷這個地址不可以寫.
思路二:
留下接口,比如我們編寫SDK程序的是否,當鼠標點擊的是否,會產生一個回調函數,那么這個回調函數是用戶寫的.因為當鼠標按下,操作系統只能通知你,但是不知道你要怎么做.
思路三:
做表,通過查表,進而判斷內存是否可以訪問或者讀寫.
這里關於前兩種思路,第一種思路,對於操作系統肯定不現實的.每次訪問內存都要判斷,校驗,不說你能不能完成,就算真的完成了,那么你的操作系統也會奇卡無比.
思路二,思路二放在我們自己編寫的是否倒是可以.但是對於操作系統來說也是不現實的.
思路三,這個可以了.我們可以通過查表的方法,進行判斷.而且只在訪問內存的是否才進行判斷內存是否可讀寫.
對於上面來說,我們就會產生一個新的疑問.這個表怎么做才合理.
在做表之前,我們要熟悉匯編中的段寄存器. 我們知道,在16位匯編中,我們可以通過段+偏移的方式來尋找內存.管理內存.那么我們現在要對內存做管理.那么就要分段了.
三丶分段管理概要
進行分段管理,來管理內存.那么我們應該怎么分.在分段之前我們要理解幾個基本的概念.
1.邏輯地址.什么是邏輯地址
2.線性地址.什么是線性地址.
3.物理地址.
4.虛擬地址(暫時不講)
邏輯地址: 邏輯地址指的是 段 + 偏移的方式,我們程序中每一行代碼都是邏輯地址.
物理地址: 物理地址就是內存條的地址,也就是我們說的實際地址.
線性地址: 線性地址我們可以理解為邏輯上連續的物理地址.
段+偏移 查表,會查到線性地址.(物理地址),每個段+偏移都會查到一塊物理地址.
比如我們的邏輯地址: 00401000~00402000,在邏輯上我們看的是連續的,但是通過查表轉換為物理地址的是否則不是連續的.
看圖:

有可能進過查表,得出的物理地址不是連續的.但是邏輯地址是連續的.
線性地址,如果我們沒有虛擬內存.那么查到的線性地址就是物理地址.如果有虛擬內存,那么可能還要查表才能轉化為物理內存.
為什么要查表得到物理地址?
原因是,我們要對進程做隔離,對內存做保護.所以我們查到對應的物理地址其實是對它做一個保護.
四丶表格式怎么做.怎么做表?
既然上面我們明白了,要對內存做保護,那么首先要分段,對每一段內存做保護.那么該怎么設計.
1.段起始地址
2.大小
3.結束地址.
4.當前內存的保護屬性.
我們會這樣設計表格.其實我們想到這樣設計,那么inter等等CPU也不是神,也會這樣設計.
看下Inter設計的表格.

每錯,第一次看到就會暈.那么仔細講解這個存儲段描述符表
首先我們理解一下 Base Address,也就是段.
段是實現虛擬地址到線性地址(物理地址)的轉化機制的基礎,也就是查表需要用到段.
那么在保護模式下.每個段有三個參數. 段基地址(Base Address) 段界限(limit),可以理解為區域
段屬性(Attributes) 這三個字段則是inter定義的表格.和我們的差不多.
Base Address: 段基地址,也就是我們分段的是否,在32位下,段基地址長32位.也就代表的我們可以分配4G個段.這些了解即可.
段界限(Limit): 段界限,指的就是當前內存起始位置加上當前段界限的大小,是屬於什么屬性的.這個在段屬性中有表明.段界限用20位來表示,注意,是位.段界限可以是以字節為單位,也可以以4K為單位.什么意思那? 也就是說.這個段界限最大是20位表示 那么界限就是 2^20次方-1*4096字節大小
計算得出:
2^20-1 * 4K = FFFFF000,然而在32為系統中不是4G大小的界限.所以進而加上0FFFH大小.
公式: LIMIT = limit(2^20) * 4k + 0FFFh. 也相當於 左移<<12位,+0FFFh.
而是否*4K則看屬性中的G位,如果G位為1,那么就*4K,如果為0,則*8位,也就是按照一個字節的界限去做.
4.1 線性地址的范圍怎么計算.
base Address + limit 則可以形成一塊內存區域.

假設段A的基地址是 00012345h,段界限為5678h,並且是以字節為單位(G = 0),那么
段基地址+ 段界限 = 000179BDh, 那么在00012345h ~ 000179BDH則是段A的線性地址
計算就是 段基地址 + 段界限 (也可以理解為,起始地址+一塊區域.則這塊區域就是線性地址)
如果屬性中 G位 = 1,那么就是按照4K去計算.
0012345h + (5678 *4K) + 0FFFh = 0568b344h
那么段A的線性地址就是從 0012345h ~ 0568b344h
我們上面計算線性地址,提供了一個表格.這個表格相信大家現在也能看懂了.

其中,我們知道了 段基地址占4個字節(32位)而段界限占20位,那么還屬性則占12位,而一種表的大小是8個字節.
看上面的圖,我們發現
M+7 存儲的是段地址
M+4,M+3,M+2 這三個字節也是存儲的段的地址.這是為什么? 因為inter為了兼容80286(24)位,那么只能添加新的東西來了,而在80286上面,是沒有多加的.
M+1 M+0 這兩個字節是16位,存儲的是段界限,而M+6的8位也是存儲的段界限的.
而M+5,M+6中.M+5全部都是段的屬性,M+6中,也有段屬性的存在.

M+6,和M+5展開查看.
其中 BLT3,BLT2,BLT1,BLT0這4位,是段界限的4位.剩余的是段屬性
4.2段屬性介紹.

根據上面的表展開得知,段屬性分別有
G D 0 AVL P DPL DT1 TYPE
那么分別是什么意思?
G : 歷史位, 當G = 1的是否,段界限需要 * 4K(0-4095),G = 0的是否,那么就是按照8位來計算,也就是一個字節.
D: D位方向位.我們的堆棧保護內存的時候,堆棧和我們正常的數據結構是相反的.段界限我們應該+那么堆棧就需要減,所以需要個方向位調整
BLT5, 保留位
AVL: 應用軟件可使用位.
P: 這個段這個內存是否有效
DPL: 特權位,判斷你是0環還是3環
DT位: 描述我們這個表的類型是用戶還是系統.DT = 1描述系統.
TYPE:位,這個則是表明了內存屬性是可讀,可寫,還是可執行.
TYPE位展開.

如果想要一塊內存可讀可執行,可寫.那么需要建立兩個表.分別讓TYPE為 = 2,然后 = 8即可.
因為段可以重疊.所以可以這樣操作,所以就有了修改內存保護屬性的API,inter官方承認的.
五丶什么是描述符,以及全局描述符表,局部描述符表.
描述符:
也就是我們說的三個字段.我們這三個字段合在一起成為了一張表.這個表則成為存儲段描述符. 存儲段信息的表.
局部描述符表:
我們知道針對我們一個進程我們可以建立多個存儲段描述符表.來保護我們的內存,那么CPU訪問的是否則會進行校驗.
那么這個則是局部描述符表.簡稱 LDT表.
那么如果多個進程我們就需要多個描述符表.各自放在自己的低2G空間,高2G空間的描述符表是一樣.
那么此時就產生了冗余問題.高2G的描述符表都是一樣的,所以建立一個全局的描述符表. 簡稱GDT
LDT表只需要操作系統給表的地址即可.這些都是操作系統在實模式啟動的是否進行填寫的.
其中LDT = A進程,那么就執行A進程的操作.切換進程,並且保存進程的各種信息.以及各種表. 如果我們換成了B進程,那么就會切換到B進程.
如果我們手動切換,則是進行內核操作了,也就是所說的ROOTKIT,(內核補丁)的技術了.(我猜大部分學習內核的都是學習這種)
六丶段選擇子,進行查表.
什么是段選擇子.段選擇子是翻譯的.我們在32為的段選擇子是我們的段寄存器. 這些段寄存器都用來保護內存了.

段當下表進行查表動作.其中后2為是RPL,也是特權指令. 如果查表的是否RPL和描述符表的DPL一至則可以進行查表.不會出錯. BLT2是表示查詢那個表, TL = 1表示是LDT表,TL = 0 表示GDT表.
3環下有讀取GDT和LDT描述符表的指令
SGDT [內存] 讀取SGDT表的起始位置到你指定的內存. 3環下可以讀不可以寫. LGDT[內存] 寫,ring3不能執行.
其中如果在ring3下執行SGDT那么操作系統給你的是一個錯誤的值.
學習內核知識建議讀書 + 視頻. 資料只能簡單看看
課堂代碼資料: 鏈接:https://pan.baidu.com/s/1qZIt6hu 密碼:quao
轉載請注明出處: http://www.cnblogs.com/iBinary/
