Linux總是以Lazy的方式給應用程序分配內存,包括堆、棧(函數調用越深,用的棧越多,最終發生page fault才得到棧)、代碼段、數據段。那么,這些已經獲得到內存的段會一直占用著內存嗎?
1.page cache
Linux下讀寫文件,主要有兩種方式:
調用read讀文件,Linux內核會申請一個page cache,然后把文件讀到page cache中,再將內核空間的page cache拷貝到用戶空間的buf。
調用write寫文件,則將用戶空間buf拷貝到內核空間page cache。
mmap
mmap可以避免buf從用戶空間到內核空間的拷貝過程。
直接把文件映射成一個虛擬地址指針,這個指針指向內核申請的page cache。內核知道page cache與硬盤中文件的對應關系。
使用mmap讀寫文件
注:讀寫權限需要對應,否則觸發page fault。
編譯執行:
mmap看起來是由一個虛擬地址對應一個文件(可以直接用指針訪問文件),本質上是把進程的虛擬地址空間映射到DRAM(內核從這片區域申請內存做page cache),而這個page cache對應磁盤中的某個文件,且Linux內核會維護page cache和磁盤中文件的交換關系。詳見下圖:
page cache可以看作內存針對磁盤的一個緩存,應用程序在寫文件時,其實只是將內容寫入了page cache,使用sync才能真的寫入文件。
ELF可執行程序頭部會記錄代碼段的位置,代碼段的本質就將ELF文件中的代碼段直接mmap映射到一個虛擬地址,且權限為R+X。
page cache可以極大的提高系統整體性能。如,進程A讀一個文件,內核空間會申請page cache與此文件對應,并記錄對應關系,進程B再次讀同樣的文件就會直接命中上一次的page cache,讀寫速度顯著提升。但注意,page cache會根據LRU算法(最近最少使用)進行替換。
演示:page cache對程序執行時間的影響
第一次多出很多硬盤io操作;第二次python的很多環境都在內存中命中了,速度提升顯著。用\time -v命令再次對比:
附注:
i.swap:
動詞:swapping,內存與磁盤的顛簸行為
名字:swap分區
ii.cache可以通過/proc/sys/vm/drop_caches強行釋放,寫1釋放page cache,2釋放dentries和inode,3釋放兩者。
2.free命令的詳細解釋
上圖中,buffers與cached都是文件系統的緩存,沒有本質區別,唯一區別是背景不同:
i.當以文件系統(ext4,xfs等)的形式去訪問文件系統中的文件,如mount /dev/sda1 /mnt后,/mnt目錄下會有很多文件,訪問這類文件所產生的cache就對應free命令顯示的cached列。
ii.直接訪問/dev/sda1時,如用戶程序直接打開open(“dev/sda1…)或執行dd命令,以及文件系統本身去訪問裸分區,所產生的cache對應free命令顯示的buffers列。
參考下圖所示:
演示:讀硬盤裸分區導致free命令顯示內容變化
linux kernel 3.14版本以后,已經采用新的free命令,如下圖:
老版本free中-/+buffers/cache的含義如下圖:
新版本free中多出available,即是評估出現在還有多少內存可供應用程序使用。
3.file-backed的頁面和匿名頁
page cache和CPU內部cache一樣,是可以被替換出去的。有文件背景的頁面可以swap到磁盤。EG. 啟動firefox,跑一個oom的程序,前后對比firefox的smaps文件。可以看出firefox在內存緊張的情況下,代碼段、mmap的字體文件等都被替換出去而不駐留內存了。
那么,沒有文件背景的匿名頁是如何交換回收的呢?是否常住內存?詳見下圖:
有文件背景的頁面和匿名頁都需要swap,有文件背景的頁面向自己的文件背景中交換,匿名頁向swap分區和swapfile中交換。即使編譯內核時將CONFIG_SWAP關閉(只是關閉了匿名頁的交換),linux內核中kswapd的線程還是會swap有文件背景的頁面。
Linux有三個水位:min,low,high。一旦內存達到低水位時,后臺自動回收直到回收到高水位。當內存到達min水位時,直接堵住進程進行回收。
匿名頁和有文件背景的頁面都有可能被回收,/proc/sys/vm/swappiness值比較大時,傾向回收匿名頁;swappiness值比較小時傾向回收有文件背景的頁面。回收算法皆為LRU。
附注:
數據段比較特殊,在沒有寫的情況是有文件背景的,但被寫后就變為匿名頁。
Windows中的虛擬內存就相當于Linux的swapfile。
4.頁面回收和LRU
如上圖,運行到第4列時,第1頁最不活躍。運行到第5列時又把第1頁踏了一次,此時第2頁變為最不活躍的。運行到第6列時又把第2頁踏了一次,此時第3頁變為最不活躍的,所以在第7列時,由于要訪問一個新的第5頁,3就被替換出去。
5.swap以及zRAM
嵌入式系統受flash限制,很少使用swap分區,一般都swapoff。所以嵌入式系統引入zRAM技術。
zRAM直接把一塊內存模擬成一個硬盤分區,當作swap分區使用,此分區自帶透明壓縮功能,當匿名頁向zRAM分區寫時,Linux內核使CPU自動對匿名頁進行壓縮。接下來,當應用程序又執行到剛才的匿名頁時,由于此頁已經被swap到zRAM中,內存中沒有命中,頁表也沒有命中,所以此時再去訪問這塊內存時再次發生page fault,Linux就從zRAM分區中將匿名頁透明的解壓出來還到內存中。
zRAM的特點是用內存來做swap分區,透明壓(兩頁匿名頁有可能被壓縮成一頁),透明解(一頁解壓成兩頁),這樣其實相當于擴大了內存,但會多損耗一些CPU。
-
Linux
+關注
關注
87文章
11345瀏覽量
210409 -
內存管理
+關注
關注
0文章
168瀏覽量
14191
原文標題:郝健: Linux內存管理學習筆記-第4節課
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
Linux內存系統: Linux 內存分配算法
內核的內存是如何進行分配的
如何通過TZASC分配安全內存并通過OP-TEE中的可信應用程序訪問它?
嵌入式Linux NFS方式下應用程序的實現
Android應用程序內存泄漏的原因及規避方法
![Android<b class='flag-5'>應用程序</b><b class='flag-5'>內存</b>泄漏的原因及規避方法](https://file.elecfans.com/web2/M00/4A/14/pYYBAGKhvJSACFHJAAA-nOUMNWk069.png)
C語言堆棧程序內存的分配
OneCommand Manager應用程序Linux版
![OneCommand Manager<b class='flag-5'>應用程序</b><b class='flag-5'>Linux</b>版](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論