簡體   English   中英

程序從哪里分配內存?

[英]From where does the program allocate memory?

作為C和C ++程序員,我使用mallocnew來分配內存。 我只是想知道:操作系統如何分配內存?

  1. 它是從RAM還是從硬盤或其他地方分配的?

  2. 為了以防萬一,我可以從硬盤借內存嗎?

它實際上比你想象的要復雜得多。 操作系統會考慮“頁面”中的所有內容,將RAM分成頁面,將硬盤分成頁面。 當您的程序啟動時,它會檢查您的可執行文件占用多少內存,為它選擇一些RAM頁面,並將這些頁面分配給您的程序。 如果RAM中沒有“可用”頁面,它會占用RAM中較舊的一些頁面,並將它們保存到隱藏在某處的硬盤驅動器中,然后將這些頁面提供給您。

在程序中分配內存時,程序的內存管理器將嘗試在操作系統分配給它的頁面中找到一個空閑位置。 如果還不夠,它會向操作系統詢問更多頁面,並且操作系統會騰出更多空間並為您的應用程序提供更多頁面。

如果您的程序有一段時間沒有使用的頁面(有時甚至是代碼),操作系統可能會將該頁面保存到硬盤驅動器,當程序再次嘗試使用該頁面時,操作系統會暫停程序,將頁面重新加載到RAM中,然后恢復您的程序。

這是一個毫無意義的圖表

C++ addresses           RAM         hard drive
+------------+    +------------+  +------------+  
| 0x00010000 |\ ->| 0x00010000 |  | 0x00010000 | 
+------------+ X  +------------+  +------------+
| 0x00020000 |/ ->| 0x00020000 |  | 0x00020000 |
+------------+    +------------+  +------------+
| 0x00030000 |-->?         /----->| 0x00030000 |
+------------+            /       +------------+
| 0x00040000 |-----------/        | 0x00040000 |
+------------+
|    etc     |

所以在這段代碼中,你的代碼的堆棧內存為0x00010000-0x0002FFFF,你已經分配了一些動態內存,那就是0x0004000。 就像你知道的那樣! 實際上,當您訪問0x0002000時,操作系統會說“哦,我已將您的那個頁面存儲在RAM地址0x00010000”中並為您讀取這些值。 您暫時沒有觸及0x00040000的頁面,因此操作系統將其保存到硬盤驅動器位置0x00030000處的硬盤驅動器,但如果您嘗試使用它,它會將其帶入RAM。 操作系統尚未提供地址0x00030000,因此如果您嘗試使用它,操作系統會告訴您該地址沒有任何實際頁面,並且您會收到分段錯誤(segfault)。 讓這個有趣的是當你要求像向量一樣的大型連續塊時,操作系統可以給你發現它周圍的任何舊頁面,它不必擔心它們是否是連續的。 它們看起來與您的程序相鄰,這一切都很重要。

這也允許操作系統隱藏一個程序的存儲器,使其無法讀取或修改其他程序的存儲空間。 他們很安全! 除了......有辦法告訴操作系統在兩個程序之間共享頁面(盡管它們在每個程序中可能有不同的地址),允許它們共享頁面。 DLL這樣做。

實際上,它比這復雜得多。

1)它是從RAM還是從硬盤或其他地方分配的?

在支持虛擬內存的現代系統/平台上,操作系統決定在何處以及如何分配/存儲內存。 系統也可以在內存或磁盤上將內存從一個地方移動到另一個地方。

2)為了以防萬一,我可以從硬盤借內存嗎?

管理內存的操作系統可以從磁盤中借用內存。

您還可以通過將數據存儲在文件中來明確地從磁盤中借用內存。 C和C ++標准庫( stdio.hfstream )支持文件操作。

當您處理由malloc或operator new分配的malloc ,它位於RAM中並具有唯一的地址。 操作系統的工作是在尋址時在RAM中使用該塊內存,但它可以自行決定將其交換到磁盤。 由於交換速度很慢,因此操作系統需要弄清楚如何最小化交換。

使用“虛擬內存”的操作系統允許您設置虛擬內存管理器可用的磁盤空間量。

雖然您可能會考慮使用數據庫來管理數據是否更好,尤其是在數據的生命周期長於單個會話時,您無需自己嘗試自行管理。

這個答案將以Linux為中心

它看起來要復雜得多。 分配內存塊時,可能會發生以下兩種情況之一。 如果您的進程已經有足夠的內存以前已釋放但未返回到操作系統(分配器通常不會),則該內存將在分配器表中標記為已分配,並將返回。 當進程還沒有內存時,分配器會向操作系統詢問更多內存。 在Linux上,這意味着brksbrk系統調用。 我不知道它在Windows或OSX上意味着什么。

所有現代的常見操作系統(Linux,Windows,OSX及其衍生產品)都使用虛擬內存,地址的概念不一定指向真正的RAM。 在你輸入內容之前,你分配的內存可能根本不存在。 一旦開始使用它,操作系統需要在RAM中為它騰出空間。 為此,操作系統會將其他未使用的頁面(部分內存)存儲在磁盤上的交換文件或分區中(如果已配置)。

操作系統不斷地在交換存儲和實際RAM之間移入和移出內存頁。 每當您的進程訪問當前不在RAM中的內存部分時,處理器會生成頁面錯誤,導致操作系統從磁盤加載該頁面,並通過移動其他頁面為內存騰出空間交換。


基本上,在現代操作系統中,內存可以來自操作系統選擇的任何位置,甚至可能在您分配時也不存在


注意:有些操作系統,比如Linux大多數時候,甚至會讓你分配它沒有給你的內存。 這稱為過度使用內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM