1. 程式人生 > 其它 >Windows記憶體管理-分段

Windows記憶體管理-分段

0x01原因

分段的產生原屬於安全問題。

一個程式可以自由的訪問不屬於它的記憶體位置,甚至可以對那些內容進行修改。這也導致安全問題 促使一種記憶體隔離的手段 分段的產生。

0x02分段原理

處理器要求在載入程式時,先定義該程式所擁有的段,然後允許使用這些段。定義段時需要基地址,段界限,特權級別,型別等。

在一個程式訪問cs,ss,ds,es 這些段時。處理器將會實施檢查,防止記憶體違規訪問。

因此有了段描述符來描述這些段的內容和許可權

0x03段描述符

認識段描述符先定義全域性描述符表GDT,為了跟蹤GDT 處理器有一個48位暫存器,也就是gdtr,分別是32位線性地址和16位邊界地址

訪問地址範圍就是0x00000000到0xffffffff 4gb 的對映範圍 界限地址 ffff 就是64kb 一個GDT大小是8個位元組 所以GDT最最多可以定義8192個描述符

下面就是段描述符格式

下面是低位,上面是高位 段基地址: 0-15+16~23+24~31 FFFF FF FF 段界限 0-15+19+16 FFFF F 0xFFFF FFFF:0FFFF 就是GDT的實體地址 G粒度位: 當為0時 段界限以位元組為單位 範圍(1b~1mb) 當為1時,段界限以4KB為界限 範圍(4kb-4gb) S描述符位: 當為0時 表示是個系統段,當為1時表示程式碼段或者資料段(棧段也是特殊的資料段) DPL特權級位: 分別表示0,1,2,3 其中0是最高位。不同級別的程式相互隔離,嚴格限制互訪。高可以訪問低特權級 P段存在位: p位表示描述符對應的段是否存在,當記憶體緊張時,可能只建立了描述符沒有建立記憶體這時P位就是0 表示段並不存在,p是有處理器負責檢查的 如果是0處理器會產生一箇中斷。這一過程由作業系統提供,負責將該段從硬碟換回記憶體。將p置為1,在多工多使用者的系統中,這是一種常用的虛擬記憶體排程策略 D/B運算元大小位或者棧指標大小位或者上部邊界標誌位
不同段表示不同意思 程式碼段表示 d=0 表示16位 d=1 表示32位 表示使用 eip還是ip 棧段表示 b=0表示使用sp b=1 表示使用 esp b位也決定上部邊界 b=0 就是 sp暫存器最大值 0xffff b=1 esp最大值 0xffff ffff L64專用位 暫時不涉及 置0即可 TYPE 描述符子型別位 對於資料段來說 4位 X,E,W,A 程式碼段 4位 X,C,R,A x表示可執行 資料段不可執行 預設為0 資料段的E表示段擴充套件方向 為0向上擴充套件 向高地址方向擴充套件。 為1向下擴充套件 向低地址擴充套件通常是棧段。 W=0表示不允許寫入 C表示特權級依從 0表示非依從的程式碼段,可以從與它特權級相同的程式碼段呼叫,或者通過門呼叫 1表示 允許從低特權級的程式轉移到該段執行。 R=0表示不能讀出 A位已訪問位 表示最近這個段是否被訪問過 每當被訪問會被置1 清理由作業系統負責 監視是否還在使用。知道使用頻率,記憶體緊張時把不常用的段退避到硬碟上,從而實現虛擬記憶體管理 AVL位
軟體位 使用者使用沒啥用 下面通過windbg除錯檢視gdt表

看到當前的gdtr 暫存器值 和當前 ds cs es值

ds 是23解析規則就是

2 3

0010 0011

00100=4

rpl 請求特權級 3就ring3 許可權

tl 0=gdtr 暫存器裡面 1=ldtr裡面

ds=23 指的就是GDT表的第4位置

可以看到前5個除了第一個用於指向null的gdt 表 其他的4個把所有型別都包括了 這是因為 微軟沒用分段來隔離記憶體 因為gdt 大小隻能8192個太少了 。

後面改用分頁來隔離記憶體了,又猶豫cpu只認段描述符這種格式,所以就做了4個把所有型別都包括的描述符 來解決這個問題。

但是fs gs 用的還是分段

這裡fs=3b

111011= 7

f892a000~00001fff

看記憶體拆分就是

01 00 00 a0 92 93 c0f8

00 0a 92 f8-01

g位為1 所以 段界限要*4kb=4096

00 00 01*4kb+0xfff 就是最後的段界限

最後就是

f892a000~1fff

從此山高路遠,縱馬揚鞭。願往後旅途,三冬暖,春不寒,天黑有燈,下雨有傘。此生盡興,不負勇往。