77%的Linux運維都不懂的內核問題
來自專欄 Linux高薪集訓營
轉載一篇文章,原文鏈接:linux內存。這篇文章是我看過為數不多的關於內存的分配和回收的好文章,可以看出作者本身對於Linux的理解非常深。
前言
之前在實習時,聽了 OOM 的分享之後,就對 Linux 內核內存管理充滿興趣,但是這塊知識非常龐大,沒有一定積累,不敢寫下,擔心誤人子弟,所以經過一個一段時間的積累,對內核內存有一定了解之後,今天才寫下這篇博客,記錄以及分享。
【OOM - Out of Memory】內存溢出
內存溢出的解決辦法:1、等比例縮小圖片2、對圖片採用軟引用,及時進行 recycle( ) 操作。
3、使用載入圖片框架處理圖片,如專業處理圖片的 ImageLoader 圖片載入框架,還有XUtils 的 BitMapUtils 來處理。
這篇文章主要是分析了單個進程空間的內存布局與分配,是從全局的視角分析下內核對內存的管理;
下面主要從以下方面介紹 Linux 內存管理:
- 進程的內存申請與分配;
- 內存耗盡之後 OOM;
- 申請的內存都在哪?
- 系統回收內存;
1、進程的內存申請與分配
之前有篇文章介紹 hello world 程序是如何載入內存以及是如何申請內存的,我在這,再次說明下:同樣,還是先給出進程的地址空間,我覺得對於任何開發人員這張圖是必須記住的,還有一張就是操作 disk ,memory 以及 cpu cache 的時間圖。
當我們在終端啟動一個程序時,終端進程調用 exec 函數將可執行文件載入內存,此時代碼段,數據段,bbs 段,stack 段都通過 mmap 函數映射到內存空間,堆則要根據是否有在堆上申請內存來決定是否映射。
exec 執行之後,此時並未真正開始執行進程,而是將 cpu 控制權交給了動態鏈接庫裝載器,由它來將該進程需要的動態鏈接庫裝載進內存。之後才開始進程的執行,這個過程可以通過 strace 命令跟蹤進程調用的系統函數來分析。
charles@charles-Aspire-4741:~$ strace ./toUpperexecve("./toUpper", ["./toUpper"], [/* 72 vars */]) = 0brk(NULL) = 0x1bef000access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f30be5d8000access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3fstat(3, {st_mode=S_IFREG|0644, st_size=116232, ...}) = 0mmap(NULL, 116232, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f30be5bb000close(3) = 0access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3read(3, "177ELF2113 3 >