C語言中文網
首頁 > 編程筆記 > 操作系統筆記 閱讀:293

內存分段機制詳解

通過學習內存分配的方式我們知道,用戶的內存視圖與實際的物理內存不一樣。這同樣適用于程序員的內存視圖。

事實上,對操作系統和程序員來說,按物理性質來處理內存是不方便的。如果硬件可以提供內存機制,以便將程序員的內存視圖映射到實際的物理內存,系統將有更多的自由來管理內存,而程序員將有一個更自然的編程環境。分段提供了這種機制。

分段的基本方法

程序員是否認為內存是一個字節的線性數組,有的包含指令而其他的包含數據?大多數程序員會說“不”。相反,程序員通常愿意將內存看作一組不同長度的段,這些段之間并沒有一定的順序(圖 1)。

程序員眼中的程序
圖 1 程序員眼中的程序

當編寫程序時,程序員認為它是由主程序加上一組方法、過程或函數所構成的。它還可以包括各種數據結構,例如對象、數組、堆棧、變量等。每個模塊或數據元素通過名稱來引用。程序員會說“堆棧”、“數學庫”和“主程序”等,而并不關心這些元素所在內存的位置,及他不關心堆棧是放在函數 Sqrt() 之前還是之后。

這些段的長度是不同的,其長度是由這些段在程序中的目的決定的。段內的元素是通過它們距段首的偏移來指定程序的第一條語句、在堆棧里的第 7 個棧幀、函數 Sqrt() 的第 5 條指令等。

分段就是支持這種用戶視圖的內存管理方案。邏輯地址空間是由一組段構成。每個段都有名稱和長度。地址指定了段名稱和段內偏移。因此用戶通過兩個量來指定地址:段名稱和段偏移。

為了實現簡單起見,段是編號的,通過段號而不是段名稱來引用。因此,邏輯地址由有序對組成:

<段號,偏移>

通常,在編譯用戶程序時,編譯器會根據輸入程序來自動構造段。

一個 C 編譯器可能會創建如下段:,
在編譯時鏈接的庫可能分配不同的段。加載程序會裝入所有這些段,并為它們分配段號。

分段硬件

雖然用戶現在能夠通過二維地址來引用程序內的對象,但是實際物理內存仍然是一維的字節序列。因此,我們應定義一個實現方式,以便映射用戶定義的二維地址到一維物理地址。這個地址是通過段表來實現的。

段表的每個條目都有段基地址和段界限。段基地址包含該段在內存中的開始物理地址,而段界限指定該段的長度。

分段硬件
圖 2 分段硬件

段表的使用如圖 2 所示。每個邏輯地址由兩部分組成:段號 s 和段偏移 d。段號用作段表的索引,邏輯地址的偏移 d 應位于 0 和段界限之間。如果不是這樣,那么會陷入操作系統中(邏輯地址試圖訪問段的外面)。如果偏移d合法,那么就與基地址相加而得到所需字節的物理內存地址。因此,段表實際上是基址寄存器值和界限寄存器值的對的數組。


圖 3 分段的例子

例如,假設如圖 3 所示的情況。有 5 個段,按 0?4 來編號。各段按如圖所示來存儲。每個段都在段表中有一個條目,它包括段在物理內存內的開始地址(基地址)和該段的長度(界限)。

例如,段 2 為 400 字節長,開始于位置 4300。因此,對段 2 字節 53 的引用映射成位置 4300 + 53 = 4353。對段 3 字節 852 的引用映射成位置 3200 (段 3 基地址)+ 852 = 4052。對段 0 字節 1222 的引用會陷入操作系統,這是由于該段僅為 1000 字節長。

所有教程

優秀文章

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo