問題一、gdb調試用戶態程序時,,其進程地址是虛擬地址還是物理地址?如何判斷進程地址的有效性?
Linux內核爲每個進程都提供一個獨立的虛擬地址空間,並且是地址連續的,這樣進程可以更方便的訪問內存。從空間佔有率考慮,並不是所有的虛擬內存都會分配物理內存,只有那些實際使用的虛擬內存才分配物理內存,內存映射用於虛擬內存地址映射到物理內存地址。
Linux內核爲每個進程維護了一張頁表,頁表中記錄了虛擬地址到物理地址的映射關係,頁表實際存儲在CPU的內存管理單元MMU上,當進程訪問的虛擬地址在頁表中不存在時,系統會產生一個缺頁中斷,進入內核空間分配物理地址,更新進程的頁表,最後再返回用戶空間,恢復進程的運行。
問題二、TLB緩存是什麼
TLB是MMU頁表中的高速緩存,TLB的訪問速度要比MMU要快,減少TLB的刷新速率,就可以提高TLB緩存的使用率,從而提高執行效率。
MMU是以頁來管理內存的,一個頁的大小默認是4k。 頁大小隻有4k,會導致的問題是頁表會非常大。32位系統4G內存,就需要100萬的頁表項。爲解決頁表項過多的問題,linux提供了兩種機制,多級頁表和大頁內存。大頁常見大小的有2M和1G的,開源項目DPDK中就採用了1G大頁內存的機制來提供TLB的命中率。
問題三、內存的生和死
1.內存的生
內存申請malloc底層實現
Brk():小於128k的內存使用brk來申請,這些內存釋放後並不會立即歸還給系統,而是被緩存起來,便於重複使用。在內存工作繁忙時,頻繁的內存申請和釋放會造成內存碎片。
Mmap() 文件映射段:大於128k的內存採用mmap文件映射段來申請,釋放時會直接將內存歸還給系統。每次mmap都會產生缺頁異常,所以頻繁的內存申請會導致大量的缺頁異常,使內核的管理負擔加重。
明確一點,當brk和mmap被調用時並沒有真正分配物理內存,只有在首次訪問時纔會觸發缺頁異常,進入內核空間來真正分配物理內存。
備註:申請1k的小對象,該如何分配內存呢?
如果也給他們分配獨立的頁,那麼太浪費內存了。Linux內核通過Slab分配器來管理小內存,主要作用是分配和釋放系統中的小對象。
2.內存的死
內存不足時,系統如何處理?
1)回收緩存 LRU算法回收最近使用最少的內存
2)回收不常訪問的內存,把不常訪問的內存直接通過交換分區寫到磁盤上。
3)OOM機制,殺死佔有內存高的進程。
內存不足時會發Swap交換,Swap 其實就是把一塊磁盤空間當成內存來用。它可以把進程暫時不用的數據存儲到磁盤中(這個過程稱爲換出),當進程訪問這些內存時,再從磁盤讀取這些數據到內存中(這個過程稱爲換入)。並且磁盤讀取的速度要遠比內存慢,所以swap會導致嚴重的內存性能問題。