對于C/C++程序員來說,內存分配再正常不過,C語言中的malloc:
int* a = (int*)malloc(sizeof(int));
C++中的new:
int* a = new int(10);
接下來的問題是變量a占用的內存是誰給我們分配的呢?
答案是運行在用戶態(tài)的內存分配器,如果你愿意,也可以繞過內存分配器自己來管理內存。
接下來的問題是a占用的內存在哪里呢?
答案是進程地址空間中的堆區(qū),堆區(qū)在這里:
內存中真的有像圖中這樣的布局嗎?
答案是: 沒有 。
這就是所謂的虛擬內存。
既然是虛擬內存那么這里的堆區(qū)又是從哪里來的呢?
答案是操作系統。
當我們在C/C++中分配內存時,內存分配器從堆區(qū)中找到可用內存,但如果沒有找到則向操作系統申請。
那么操作系統又是從哪里找到的內存呢?
答案是:操作系統從物理內存中找到一塊可用內存分配出去。
問題來了,既然操作系統管理的是物理內存,而操作系統分配給進程的又是虛擬內存,精神分裂啊有沒有,這是怎么一回事呢?
原來這并不沖突,操作系統會為每個進程分配一張表,記錄了從虛擬內存到物理內存的映射,這張表就叫頁表。
因此,盡管操作系統管理的是物理內存,但進程或者說程序員是看不到物理內存的,我們只能看到虛擬內存,程序運行時在發(fā)送內存讀寫指令時MMU會將虛擬內存轉換為物理內存。
接下來的問題是頁表在哪里?
答案是: 在內存中 。
你可以將頁表放在內存中的任何位置上,只要能告訴CPU在哪里即可。
誰來負責構造頁表呢?答案是操作系統,操作系統負責創(chuàng)建頁表,頁表本質上就是一個數組,處理器規(guī)定頁表的格式,操作系統按照這種格式構建好頁表,創(chuàng)建好后即可告訴CPU。
該怎樣告訴CPU呢?
答案是:通過寫特定的寄存器。
CPU中有特定的寄存器,以x86處理器為例,其中的控制寄存器cr3就用來保存頁表的地址,假設指針pagetable指向頁表,那么可以這樣設置:
mov $(pagetable), %eax
mov %eax, %cr3
pagetable必須是物理地址,頁表本身就用來將虛擬地址轉為物理地址,因此向cr3中寫入虛擬地址是沒有道理的。
接下來的問題是什么時候將頁表寫入cr3寄存器呢?
答案是:很多時候,操作系統初始化階段、進程切換時等。
現在你應該知道了吧,其實內存管理(段式管理、頁式管理)是處理器提供的一種機制,操作系統只是這種機制的使用者,我們常說的虛擬內存是處理器本身的一種能力, 如果處理器本身不提供這種能力,那么操作系統自己是很難高效實現虛擬內存的 。
CPU才是管理內存真正的大boss。
實際上如果你去看類似x86這樣的處理器編程手冊時就會發(fā)現,我們在操作系統課中熟悉的很多概念其實是處理器這種硬件提供的,操作系統僅僅是利用這些硬件的一層軟件。
因此,從這個角度看,操作系統僅僅是CPU的一個“驅動程序”而已。
-
cpu
+關注
關注
68文章
10882瀏覽量
212236 -
內存
+關注
關注
8文章
3037瀏覽量
74150 -
分配器
+關注
關注
0文章
194瀏覽量
25778
發(fā)布評論請先 登錄
相關推薦
評論