內存分段機制


我們可以寫一段簡單的c代碼(code/memory/segment_1.c):

#include <stdio.h>
int main()
{
   int a = 1;
   printf("Hello, World!");
   return 0;
}

然后將其轉為匯編,運行:

gcc -S segment_1.c

之后會生成一個.s 文件(code/memory/segment_1.s),不用細看內容。

我們發現,這個匯編代碼中,有 .string main .text,反正分為不同的塊。

	.file	"segment_1.c"
	.text
	.section	.rodata
.LC0:
	.string	"Hello, World!"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	$1, -4(%rbp)
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits

進程在內存中,主要是按照這種形式進行存儲的。

為什么要分段呢?

我們看上面那張圖片,分為不同段,每個段的讀寫屬性是不同的。比如正文段存儲代碼,就像我們上面的.s文件中的main部分。它在內存中是始終不變的,我們CPU就是從main中去取指執行。所以,它是只讀的。

而其他部分,也許是可讀可寫的。

通過分段,可以對不同的屬性代碼、數據進行更方便的管理。如果是打亂的放在內存中,那么讀寫屬性就很難控制。

所以通過分段機制,我們可以更好得控制不同段的屬性,這有利於內存的組織安排。更多的好處,可以后面慢慢體會。

分段機制與間接尋址

因為現在引入了分段機制,所以如果我們想要訪問某個地方的數據,指令,我們會引入間接尋址。

比如說,程序現在運行在代碼段(CS),然后呢,他想要訪問數據段的某個數據(DS),那么就可以使用 DS的基地址+偏移量,就可以訪問到數據段中的數據了。

就像我們下圖一樣,如果我們運行到某一條指令,他需要 DS:1 的數據,那么我們可以通過數據段開始的地址0x100 加上偏移量1,就可以直接訪問到 int a = 1 了。

所以,我們只需要知道不同段的開始地址加上偏移量,就可以訪問不同段的內容。

分段機制與LDT表

我們前面說到,因為分段機制,所以,如果我們想要去訪問某個段中的內容,我們需要獲得每個段的基址。所以,我們需要一個結構去儲存每個段的基址。這就是 LDT (本地描述表/local descriptor table) 表。

(名字,有點。。。,至少本地兩字說明,這個表是局部的,對於每個進程,都有一個LDT表)。

LDT 表

現在來說說 LDT 表,之前說了分段的好處,那么我們應該怎么設計 LDT 表呢?

我們需要用一些位來表示:可讀/可寫狀態,不同段的基址以及段的長度。

現在,我們可以通過每個進程的 LDT 表找到每個段所在的位置。

GDT 表

那么我們如何找到每個進程的 LDT 表呢?

這個,就輪到 GDT表了,與之前的 LDT 表,就差一個字母。G的意思,就是 global 全局的意思。

那意味着這張表,所有的進程都可以看到,進行訪問。

在 GDT 表中,有着不同 LDT 表的地址。這里涉及到 LDTR寄存器,這個寄存器被賦值為 GDT表中的一個 LDT 表的位置,然后CPU 可以通過這個寄存器,找到對應的進程的 LDT表。

可以看下下圖。

關於更多的 GDT 和 LDT 的介紹,可以看最后的參考部分。

分段機制與多進程

我們知道,CPU會采用某種策略,運行多個進程。這個時候,我們就需要保證不同的進程的內容,會存在不同的內存中,不能相互干擾。

這就要求,我們之前說的,每個進程都有一個 LDT表。可以將不同的進程內容映射到不同的內存地址。

總結

最后,就拿這張圖來總結下吧,大家可以用這張圖來回顧下前面的內容。

參考

《深入理解計算機系統》

  • 7.9 加載可執行目標文件

《Linux 內核0.11完全注釋》

  • 4.3 分頁機制(進階)

操作系統(哈工大李治軍老師)32講(全)超清 P20 L20 內存使用與分段

GDT(全居描述符表)和LDT(局部描述符表)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM