Linux記憶體布局、記憶體配置原理__Linux

來源:互聯網
上載者:User
Linux的虛擬記憶體管理有幾個關鍵概念


1.每個進程有獨立的虛擬位址空間,進程訪問的虛擬位址並不是真正的物理地址


2.虛擬位址可通過每個進程的頁表與物理地址進行映射,獲得真正物理地址


3.如果虛擬位址對應的物理地址不在實體記憶體中,則產生缺頁中斷,並真正分配物理地址,同時更新進程的頁表;如果此時實體記憶體已耗盡,則根據記憶體替換演算法淘汰部分頁面至物理磁碟中。

 


Linux進程虛擬位址分布


Linux使用虛擬位址空間,大大增加了進程的定址空間,由低地址到高地址分別為


唯讀段:該部分空間只能讀,不可寫。包括程式碼片段、rodata段(C常量字串和#define定義的常量)

 

資料區段儲存全域變數、靜態變數的空間

 

堆:就是平時所說的動態記憶體, malloc/new大部分都來源於此。其中堆頂的位置可通過函數brk和sbrk進行動態調整。

 

檔案對應地區:如動態庫、共用記憶體等映射物理空間的記憶體,一般是mmap函數所分配的虛擬位址空間

 

棧:用於維護函數調用的上下文空間,一般為8M,可通過ulimit –s查看。

 

核心虛擬空間:使用者代碼不可見的記憶體地區,由核心管理。 


32位系統有4G的地址空間,其中0x08048000~0xbfffffff 是使用者空間,0xc0000000~0xffffffff是核心空間,包括核心代碼和資料、與進程相關的資料結構(如頁表、核心棧等)。


64位Linux一般使用48位來表示虛擬位址空間,40位表示物理地址,這可通過 /proc/cpuinfo 來查看

address sizes   : 40 bits physical, 48 bits virtual

 


malloc是如何分配記憶體的。


malloc是glibc中記憶體配置函數,也是最常用的動態記憶體分配函數,其記憶體必須通過free進行釋放,否則導致記憶體泄露。關於 malloc 獲得虛存空間的實現,與glibc的版本有關,但大體邏輯是:


1.申請128k以內的記憶體,調用sbrk(),在堆內分配,將堆頂指標向高地址移動,獲得新的虛存空間。虛擬位址比較小。

 

2.每次分配的記憶體位址前16位元組(64位系統,32位是8位元組)是記錄該記憶體塊的控制資訊(用於 free )。

 

3.並不是每次malloc都會導致堆頂的增大,如果堆內有足夠剩餘空間,堆頂不會發生變化。

 

4.當分配大小大於128k,使用mmap在檔案對應地區中分配匿名虛存空間獲得地址空間,地址一般比較大(靠近棧區間)

 

5可通過函數mallopt(M_MMAP_THRESHOLD, 64*1024) 修改使用 mmap 的臨界值為 64k ,後續大於 64k 的分配就會使用 mmap.

 


malloc分配多大的記憶體,就佔用多大的實體記憶體空間嗎。


malloc分配的的記憶體是虛擬位址空間

 

1.VSZ並不是每次malloc後都增長,因為可重用堆頂內剩餘的空間,這樣的malloc是很輕量快速的。

 

2.如果VSZ發生變化,基本與分配記憶體量相當,因為VSZ是計算虛擬位址空間總大小。

 

3.RSS的增量很少,是因為malloc分配的記憶體並不就馬上分配實際儲存空間,只有第一次使用,發現虛存對應的物理頁面未分配,產生缺頁中斷,才真正分配物理頁面,同時更新進程頁面的映射關係(按需分配)。

 

4.由於每個實體記憶體頁面大小是4k,不管memset其中的1k還是5k、7k,實際佔用實體記憶體總是4k的倍數。所以RSS的增量總是4k的倍數。

 

  如何查看進程虛擬位址空間的使用方式。

pmap

 


free的記憶體真的釋放了?


使用mmap分配的記憶體會調用munmap系統調用來釋放,並會真正釋放該空間。

 

free釋放記憶體,在glibc中,僅僅是標記為可用,形成一個記憶體空洞(片段),並沒有真正釋放

 

glibc的free實現中,只要堆頂附近釋放總空間(包括合并的空間)超過128k,即會調用sbrk(-SIZE)來回溯堆頂指標,將原堆頂空間還給OS。否則都成為片段(片段如果相鄰會適當合并)

 


程式碼中malloc的記憶體都有相應的free,就不會出現記憶體泄露了嗎。


隨著系統頻繁地malloc和free,尤其對於小塊記憶體,堆內將產生越來越多停用片段,導致“記憶體泄露”。而這種“泄露”現象使用valgrind是無法檢測出來的。

 


既然堆內記憶體不能直接釋放,為什麼不全部使用mmap來分配。


使用mmap分配1M空間,第一次調用產生了大量缺頁中斷(1M/4K次)。缺頁中斷是核心行為,會導致核心態CPU消耗較大。

 

堆是一個連續空間,並且堆內片段由於沒有歸還OS,如果可重用片段,再次訪問該記憶體很可能不需產生任何系統調用和缺頁中斷,這將大大降低CPU的消耗。

 


如何查看進程的缺頁中斷資訊。


ps -omajflt,minflt -C <program_name>

ps -omajflt,minflt -p <pid>


其中majflt表major fault,指大錯誤。mnflt代表minor fault,指小錯誤。這兩個數值表示一個進程自啟動以來所發生的缺頁中斷的次數。其中majflt與minflt的不同是,majflt表示需要讀寫磁碟,可能是記憶體對應頁面在磁碟中需要load到實體記憶體中,也可能是此時實體記憶體不足,需要淘汰部分物理頁面至磁碟中


如果進程的核心態CPU使用過多,其中一個原因就可能是單位時間的缺頁中斷次數多個,可通過以上命令來查看。


如果MAJFLT過大,很可能是記憶體不足。


如果MINFLT過大,很可能是頻繁分配/釋放大塊記憶體(128k),malloc使用mmap來分配。對於這種情況,可通過mallopt(M_MMAP_THRESHOLD, <SIZE>)增大臨界值,或程式實現記憶體池。

 


如何查看堆內記憶體的片段情況


可通過mallinfo結構中的fsmblks、smblks、ordblks值得到,這些值表示不同大小區間的片段總個數,這些區間分別是0~80位元組,80~512位元組,512~128k。如果fsmblks、 smblks的值過大,那片段問題可能比較嚴重了

 


除了glibc的malloc/free,還有其他第三方實現嗎。


google的tcmalloc和facebook的jemalloc

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.