linux有意避開了分段機制

2021-06-22 23:26:38 字數 3003 閱讀 5039

在邏輯位址轉為線性位址的時候,我們說過,用段暫存器中的值的前

13位當作索引來索引全域性描述符表,

在linux中,滑稽的是,它有意地採用數值來繞開了分段機制,對記憶體的管理主要採用了分頁機制。

是怎樣的呢?

先看看,

linux在

gtd中放入了些什麼。檢視檔案

arch/i386/head.s

.quad 0x00cf9a000000ffff /* 0x60 kernel 4gb code at 0x00000000 */

.quad0x00cf92000000fff  /* 0x68 kernel 4gb data at 0x00000000 */

.quad0x00cffa000000ffff /* 0x73 user 4gb code at 0x00000000 */

.quad0x00cff2000000ffff/* 0x7b user 4gb data at 0x00000000 */

這裡僅僅摘下了

12-15項的內容,且看下面。

我們再來看看在在各個段暫存器中的選擇子是寫什麼數字,看看

include/asm-i386/segment.h中的定義。

include/asm-i386/segment.h

#definegdt_entry_default_user_cs 14

#define__user_cs (gdt_entry_default_user_cs * 8 + 3)

#definegdt_entry_default_user_ds 15

#define__user_ds (gdt_entry_default_user_ds * 8 + 3)

#definegdt_entry_kernel_base 12

#definegdt_entry_kernel_cs (gdt_entry_kernel_base + 0)

#define__kernel_cs (gdt_entry_kernel_cs * 8)

#definegdt_entry_kernel_ds  (gdt_entry_kernel_base + 1)

#define__kernel_ds (gdt_entry_kernel_ds * 8)

把其中的巨集替換成數值,則為:

#define__user_cs 115        [000000001110  0  11]

#define__user_ds 123        [000000001111  0  11]

#define__kernel_cs 96      [00000000 1100  0 00]

#define__kernel_ds 104    [00000000 1101  0  00]

方括號後是這四個段選擇符的

16位二制表示,它們的索引號和

t1字段值也可以算出來了

__user_cs             index= 14   t1=0

__user_ds              index= 15   t1=0

__kernel_cs          index=  12  t1=0

__kernel_ds          index= 13   t1=0

可以看到,使用者**段的暫存器中

usre_cs 115

把它拆開,用來索引

gdt時,即找到第

14項,可以看到

.quad 0x00cffa000000ffff /* 0x73 user 4gb code at 0x00000000 */

第16-31位全部為

0,即段的起始位址為

0,那麼邏輯位址轉為線性位址 即

0x00000000+偏移

=偏移。

這不是偶然現象,而是所有的情況都是這樣的,不信可以在

linux下用

gdb除錯程式輸出暫存器的值看看,是不是

115或者

123。(段暫存器)

這裡可以看自己隨便寫的函式然後除錯的結果。

可以看到

cs等幾個暫存器的值一直都是使用者

cs和ds即

115 123 。

不是偶然》。。。。

那麼可以看到,邏輯位址和線性位址有著同樣的形式(即數字上是一樣的。)

故linux記憶體管理主要是採用分頁,避開了分段(但硬體要求分段,故採用了避開的手段),但後面的

3位(段選擇子後面

3位用來表示段的級別的,

00-11是有用的,訪問

gdt還是

ldt是有用的)。

這個圖可能更清楚:

繼而由線—物

我們知道

linux

中使用者程序線性位址能定址的範圍是0-

3g,那麼是不是需要提前先把這

3g虛擬記憶體的頁表都建立好呢?一般情況下,物理記憶體是遠遠小於

3g的,加上同時有很多程序都在執行,根本無法給每個程序提前建立

3g的線性位址頁表。

linux

利用cpu

的乙個機制解決了這個問題。程序建立後我們可以給頁目錄表的表項值都填0,

cpu在查詢頁表時,如果表項的內容為

0,則會引發乙個缺頁異常,程序暫停執行,

linux

核心這時候可以通過一系列複雜的演算法給分配乙個物理頁,並把物理頁的位址填入表項中,程序再恢復執行。當然程序在這個過程中是被蒙蔽的,它自己的感覺還是正常訪問到了物理記憶體。

linux分段分頁機制

mmu使用分段單元硬體把邏輯位址轉換為虛擬位址,再使用分頁單元硬體把虛擬位址轉換為實體地址。因為這兩部分表示乙個獨一無二的邏輯位址,虛擬位址作為這個段位址另一種形式,當然也需要這兩個部分作為轉換的 原材料。這裡涉及乙個叫做段的暫存器,它的作用是放段選擇符 識別符號 共有六種 cs 儲存指向 的段的選...

Linux記憶體定址 分段機制

一 實體地址 虛擬位址和線性位址 將主機板上的物理記憶體條所提供的記憶體空間定義為物理記憶體空間,其中每個記憶體單元的實際位址是實體地址 將應用程式設計師看到的記憶體空間定義為虛擬位址空間,其中的位址是虛擬位址。線性位址空間是指一段連續的,不分段的,範圍從0到4gb的位址空間,乙個線性位址就是線性位...

Linux之分段機制和分頁機制

通用作業系統的設計原則 盡量縮短系統的平均響應時間並提高系統的吞吐率,在單位時間內為盡可能多的為使用者請求提供服務。如對於整個系統來說,注重所有任務的平均響應時間而不關心單個任務的響應時間,對於某個單個任務來說,注重每次執行的平均響應時間而不關心某次特定執行的響應時間。比如記憶體管理中的lru替換策...