大家好,我是小林。
早上看到讀者在群里討論這些面試題:
其中,第一個問題「在 4GB 物理內存的機器上,申請 8G 內存會怎么樣?」存在比較大的爭議,有人說會申請失敗,有的人說可以申請成功。
這個問題在沒有前置條件下,就說出答案就是耍流氓。因為在 32 位操作系統和 64 位操作系統場景下,答案是不同的。
另外,我們還要看申請完 8G 內存后會不會被使用,會被使用是一種情況,不會被使用又是另外一種情況了。
所以,我們要分場景討論。
應用程序通過 malloc 函數申請內存的時候,實際上申請的是虛擬內存,此時并不會分配物理內存。
當應用程序讀寫了這塊虛擬內存,CPU 就會去訪問這個虛擬內存, 這時會發現這個虛擬內存沒有映射到物理內存, CPU 就會產生缺頁中斷,進程會從用戶態切換到內核態,并將缺頁中斷交給內核的 Page Fault Handler (缺頁中斷函數)處理。
缺頁中斷處理函數會看是否有空閑的物理內存:
如果有,就直接分配物理內存,并建立虛擬內存與物理內存之間的映射關系。如果沒有空閑的物理內存,那么內核就會開始進行回收內存的工作,如果回收內存工作結束后,空閑的物理內存仍然無法滿足此次物理內存的申請,那么內核就會放最后的大招了觸發 OOM (Out of Memory)機制。32 位操作系統和 64 位操作系統的虛擬地址空間大小是不同的,在 Linux 操作系統中,虛擬地址空間的內部又被分為內核空間和用戶空間兩部分,如下所示:
通過這里可以看出:
32?位系統的內核空間占用1G?,位于最高處,剩下的3G是用戶空間;64?位系統的內核空間和用戶空間都是128T,分別占據整個內存空間的最高和最低處,剩下的中間部分是未定義的。現在可以回答這個問題了:在 32 位操作系統、4GB 物理內存的機器上,申請 8GB 內存,會怎么樣?
因為 32 位操作系統,進程最多只能申請 3 GB 大小的虛擬內存空間,所以進程申請 8GB 內存,在申請虛擬內存階段就會失?。ㄎ沂稚蠜]有 32 位操作系統測試,我估計失敗的原因是 OOM)。
在 64 位操作系統、4GB 物理內存的機器上,申請 8G 內存,會怎么樣?
64 位操作系統,進程可以使用 128 TB 大小的虛擬內存空間,所以進程申請 8GB 內存是沒問題的,因為進程申請內存是申請虛擬內存,只要不讀寫這個虛擬內存,操作系統就不會分配物理內存。
我們可以簡單做個測試,我的服務器是 64 位操作系統,但是物理內存只有 2 GB。
現在,我在機器上,申請 4 GB 內存,注意下面代碼只是單純分配了虛擬內存,并沒有使用該虛擬內存:
#include 然后運行這個代碼,可以看到,我的物理內存雖然只有 2GB,但是程序正常分配了 4GB 大小的虛擬內存: 我們可以通過下面這條命令查看進程的虛擬內存大?。?/p> # ps aux | grep alloc_4gUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 7797 0.0 0.0 4198540 352 pts/1 S+ 16:58 0:00 ./alloc_4g 其中,VSZ 就代表進程使用的虛擬內存大小,RSS 代表進程使用的物理內存大小??梢钥吹?,VSZ 大小為 4198540,也就是 4GB 的虛擬內存。 然后,我們改一下代碼,在申請完虛擬內存后,通過 memset 函數使用這個虛擬內存,看看會發生什么。 #include 運行結果: 可以看到,在申請了 2GB 虛擬內存后,然后馬上使用了這塊虛擬內存,由于這臺機器的物理內存只有 2 GB,所以發生了 OOM。 至此, 驗證完成了。簡單總結下:
X 關閉
X 關閉

