精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

我做了個實驗-malloc如何動態內存分配?

系統 Linux
在 Linux 操作系統中,虛擬地址空間的內部又被分為內核空間和用戶空間兩部分,不同位數的系統,地址空間的范圍也不同。

最近想多寫一些內存管理的文章,這次我們就以 malloc 動態內存分配為切入點,我在文中也做了小實驗:

  • malloc 是如何分配內存的?
  • malloc 分配的是物理內存嗎?
  • malloc(1) 會分配多大的內存?
  • free 釋放內存,會歸還給操作系統嗎?

free() 函數只傳入一個內存地址,為什么能知道要釋放多大的內存?

發車!

Linux 進程的內存分布長什么樣?

在 Linux 操作系統中,虛擬地址空間的內部又被分為內核空間和用戶空間兩部分,不同位數的系統,地址空間的范圍也不同。比如最常見的 32 位和 64 位系統,如下所示:

通過這里可以看出:

  • 32 位系統的內核空間占用 1G,位于最高處,剩下的 3G 是用戶空間;
  • 64 位系統的內核空間和用戶空間都是 128T,分別占據整個內存空間的最高和最低處,剩下的中間部分是未定義的。

再來說說,內核空間與用戶空間的區別:

  • 進程在用戶態時,只能訪問用戶空間內存
  • 只有進入內核態后,才可以訪問內核空間的內存

雖然每個進程都各自有獨立的虛擬內存,但是每個虛擬內存中的內核地址,其實關聯的都是相同的物理內存。這樣,進程切換到內核態后,就可以很方便地訪問內核空間內存。

接下來,進一步了解虛擬空間的劃分情況,用戶空間和內核空間劃分的方式是不同的,內核空間的分布情況就不多說了。

我們看看用戶空間分布的情況,以 32 位系統為例,我畫了一張圖來表示它們的關系:

通過這張圖你可以看到,用戶空間內存從低到高分別是 6 種不同的內存段:

  • 程序文件段,包括二進制可執行代碼
  • 已初始化數據段,包括靜態常量
  • 未初始化數據段,包括未初始化的靜態變量
  • 堆段,包括動態分配的內存,從低地址開始向上增長
  • 文件映射段,包括動態庫、共享內存等,從低地址開始向上增長(跟硬件和內核版本有關 )
  • 棧段,包括局部變量和函數調用的上下文等。棧的大小是固定的,一般是 8 MB。當然系統也提供了參數,以便我們自定義大小

在這 6 個內存段中,堆和文件映射段的內存是動態分配的。比如說,使用 C 標準庫的 malloc() 或者 mmap() ,就可以分別在堆和文件映射段動態分配內存。

malloc 是如何分配內存的?

實際上,malloc() 并不是系統調用,而是 C 庫里的函數,用于動態分配內存。

malloc 申請內存的時候,會有兩種方式向操作系統申請堆內存。

  • 方式一:通過 brk() 系統調用從堆分配內存
  • 方式二:通過 mmap() 系統調用在文件映射區域分配內存

方式一實現的方式很簡單,就是通過 brk() 函數將「堆頂」指針向高地址移動,獲得新的內存空間。如下圖:

方式二通過 mmap() 系統調用中「私有匿名映射」的方式,在文件映射區分配一塊內存,也就是從文件映射區“偷”了一塊內存。如下圖:

什么場景下 malloc() 會通過 brk() 分配內存?又是什么場景下通過 mmap() 分配內存?

malloc() 源碼里默認定義了一個閾值:

  • 如果用戶分配的內存小于 128 KB,則通過 brk() 申請內存
  • 如果用戶分配的內存大于 128 KB,則通過 mmap() 申請內存

malloc() 分配的是物理內存嗎?

不是的,malloc() 分配的是虛擬內存。

如果分配后的虛擬內存沒有被訪問的話,是不會將虛擬內存不會映射到物理內存,這樣就不會占用物理內存了。

只有在訪問已分配的虛擬地址空間的時候,操作系統通過查找頁表,發現虛擬內存對應的頁沒有在物理內存中,就會觸發缺頁中斷,然后操作系統會建立虛擬內存和物理內存之間的映射關系。

malloc(1) 會分配多大的虛擬內存?

malloc() 在分配內存的時候,并不是老老實實按用戶預期申請的字節數來分配內存空間大小,而是會預分配更大的空間作為內存池。

具體會預分配多大的空間,跟 malloc 使用的內存管理器有關系,我們就以 malloc 默認的內存管理器(Ptmalloc2)來分析。

接下里,我們做個實驗,用下面這個代碼,通過 malloc 申請 1字節的內存時,看看操作系統實際分配了多大的內存空間。

#include <stdio.h>
#include <malloc.h>

int main() {
printf("使用cat /proc/%d/maps查看內存分配\n",getpid());

//申請1字節的內存
void *addr = malloc(1);
printf("此1字節的內存起始地址:%x\n", addr);
printf("使用cat /proc/%d/maps查看內存分配\n",getpid());

//將程序阻塞,當輸入任意字符時才往下執行
getchar();

//釋放內存
free(addr);
printf("釋放了1字節的內存,但heap堆并不會釋放\n");

getchar();
return 0;
}

執行代碼:

我們可以通過 /proc//maps 文件查看進程的內存分布情況。我在 maps 文件通過此 1 字節的內存起始地址過濾出了內存地址的范圍。

[root@xiaolin ~]# cat /proc/3191/maps | grep d730
00d73000-00d94000 rw-p 00000000 00:00 0

這個例子分配的內存小于 128 KB,所以是通過 brk() 系統調用向堆空間申請的內存,因此可以看到最右邊有 [heap] 的標識。

可以看到,堆空間的內存地址范圍是 00d73000-00d94000,這個范圍大小是 132KB,也就說明了 malloc(1) 實際上預分配 132K 字節的內存。

可能有的同學注意到了,程序里打印的內存起始地址是 d73010,而 maps 文件顯示堆內存空間的起始地址是 d73000,為什么會多出來 0x10 (16字節)呢?這個問題,我們先放著,后面會說。

free 釋放內存,會歸還給操作系統嗎?

我們在上面的進程往下執行,看看通過 free() 函數釋放內存后,堆內存還在嗎?

從下圖可以看到,通過 free 釋放內存后,堆內存還是存在的,并沒有歸還給操作系統。

這是因為與其把這 1 字節釋放給操作系統,不如先緩存著放進 malloc 的內存池里,當進程再次申請 1 字節的內存時就可以直接復用,這樣速度快了很多。

當然,當進程退出后,操作系統就會回收進程的所有資源。

上面說的 free 內存后堆內存還存在,是針對 malloc 通過 brk() 方式申請的內存的情況。

如果 malloc 通過 mmap 方式申請的內存,free 釋放內存后就會歸歸還給操作系統。

我們做個實驗驗證下, 通過 malloc 申請 128 KB 字節的內存,來使得 malloc 通過 mmap 方式來分配內存。

#include <stdio.h>
#include <malloc.h>

int main() {
//申請1字節的內存
void *addr = malloc(128*1024);
printf("此128KB字節的內存起始地址:%x\n", addr);
printf("使用cat /proc/%d/maps查看內存分配\n",getpid());

//將程序阻塞,當輸入任意字符時才往下執行
getchar();

//釋放內存
free(addr);
printf("釋放了128KB字節的內存,內存也歸還給了操作系統\n");

getchar();
return 0;
}

執行代碼:

查看進程的內存的分布情況,可以發現最右邊沒有 [head] 標志,說明是通過 mmap 以匿名映射的方式從文件映射區分配的匿名內存。

然后我們釋放掉這個內存看看:

再次查看該 128 KB 內存的起始地址,可以發現已經不存在了,說明歸還給了操作系統。

對于 「malloc 申請的內存,free 釋放內存會歸還給操作系統嗎?」這個問題,我們可以做個總結了:

  • malloc 通過 brk() 方式申請的內存,free 釋放內存的時候,并不會把內存歸還給操作系統,而是緩存在 malloc 的內存池中,待下次使用
  • malloc 通過 mmap() 方式申請的內存,free 釋放內存的時候,會把內存歸還給操作系統,內存得到真正的釋放。

為什么不全部使用 mmap 來分配內存?

因為向操作系統申請內存,是要通過系統調用的,執行系統調用是要進入內核態的,然后在回到用戶態,運行態的切換會耗費不少時間。

所以,申請內存的操作應該避免頻繁的系統調用,如果都用 mmap 來分配內存,等于每次都要執行系統調用。

另外,因為 mmap 分配的內存每次釋放的時候,都會歸還給操作系統,于是每次 mmap 分配的虛擬地址都是缺頁狀態的,然后在第一次訪問該虛擬地址的時候,就會觸發缺頁中斷。

也就是說,頻繁通過 mmap 分配的內存話,不僅每次都會發生運行態的切換,還會發生缺頁中斷(在第一次訪問虛擬地址后),這樣會導致 CPU 消耗較大。

為了改進這兩個問題,malloc 通過 brk() 系統調用在堆空間申請內存的時候,由于堆空間是連續的,所以直接預分配更大的內存來作為內存池,當內存釋放的時候,就緩存在內存池中。

等下次在申請內存的時候,就直接從內存池取出對應的內存塊就行了,而且可能這個內存塊的虛擬地址與物理地址的映射關系還存在,這樣不僅減少了系統調用的次數,也減少了缺頁中斷的次數,這將大大降低 CPU 的消耗。

既然 brk 那么牛逼,為什么不全部使用 brk 來分配?

前面我們提到通過 brk 從堆空間分配的內存,并不會歸還給操作系統,那么我們那考慮這樣一個場景。

如果我們連續申請了 10k,20k,30k 這三片內存,如果 10k 和 20k 這兩片釋放了,變為了空閑內存空間,如果下次申請的內存小于 30k,那么就可以重用這個空閑內存空間。

但是如果下次申請的內存大于 30k,沒有可用的空閑內存空間,必須向 OS 申請,實際使用內存繼續增大。

因此,隨著系統頻繁地 malloc 和 free ,尤其對于小塊內存,堆內將產生越來越多不可用的碎片,導致“內存泄露”。而這種“泄露”現象使用 valgrind 是無法檢測出來的。

所以,malloc 實現中,充分考慮了 sbrk 和 mmap 行為上的差異及優缺點,默認分配大塊內存 (128KB) 才使用 mmap 分配內存空間。

free() 函數只傳入一個內存地址,為什么能知道要釋放多大的內存?

還記得,我前面提到, malloc 返回給用戶態的內存起始地址比進程的堆空間起始地址多了 16 字節嗎?

這個多出來的 16 字節就是保存了該內存塊的描述信息,比如有該內存塊的大小。

這樣當執行 free() 函數時,free 會對傳入進來的內存地址向左偏移 16 字節,然后從這個 16 字節的分析出當前的內存塊的大小,自然就知道要釋放多大的內存了。

責任編輯:武曉燕 來源: 小林coding
相關推薦

2022-01-13 10:30:21

C語言內存動態

2022-01-07 15:10:53

C++動態內存

2025-09-26 05:11:00

2024-10-11 10:00:20

2010-08-18 10:05:28

Hyper-V動態內存

2023-12-27 13:55:00

C++內存分配機制new

2010-12-09 10:03:17

Hyper-V R2

2025-02-10 03:00:00

2025-05-29 03:20:00

2010-03-01 09:09:21

Windows 8動態內存

2010-03-02 08:53:59

Windows 8動態內存

2024-01-26 16:28:28

C++動態內存開發

2022-04-26 06:21:59

編程動態內存

2025-10-28 01:10:00

2012-04-01 14:38:06

Windows Ser虛擬化

2025-03-26 00:00:05

2011-05-24 16:39:09

Cfree()

2018-06-06 08:28:37

Spark內存管理

2022-02-22 20:35:22

公鑰私鑰數據

2011-07-28 10:03:53

Hyper-V動態內存
點贊
收藏

51CTO技術棧公眾號

国产亚洲午夜| 国产精品美女在线观看直播| 国产精品丝袜黑色高跟| 91久久久久久久久久| 久久精品亚洲无码| 久久91精品| 欧美一卡在线观看| av观看免费在线| 欧美激情黑人| 99视频一区二区| 国产精品直播网红| 国产美女喷水视频| 成人免费观看49www在线观看| 亚洲一二三四区| 亚洲图色在线| 天堂在线中文| 黑人精品欧美一区二区蜜桃 | 欧美三级日韩在线| 香港三级日本三级a视频| 久草在现在线| 成人免费看黄yyy456| 国产精品视频一区国模私拍| 国产午夜福利精品| 亚洲色图插插| 中文字幕亚洲欧美一区二区三区| 中文字幕一二三| 成人亚洲综合| 在线观看一区不卡| www一区二区www免费| 1区2区3区在线视频| 国产拍欧美日韩视频二区| 国产色综合一区二区三区| 国产在成人精品线拍偷自揄拍| 国产精品久久久亚洲一区| 久久91精品国产| 亚洲熟女毛茸茸| 成人vr资源| 亚洲性av网站| 日韩在线免费观看av| 黄色欧美在线| 337p日本欧洲亚洲大胆精品| 日韩av自拍偷拍| 成人看片在线观看| 色偷偷久久人人79超碰人人澡| 人妻夜夜添夜夜无码av| 欧美78videosex性欧美| 亚洲三级免费观看| 特级西西444| 黄色免费网站在线| 亚洲欧美aⅴ...| 永久免费在线看片视频| 免费在线观看黄色| 亚洲图片你懂的| 日日噜噜噜夜夜爽爽| 日本在线观看免费| 亚洲同性gay激情无套| avove在线观看| 亚洲精品一区二区三区樱花| 老熟妇高潮一区二区三区| 久久国产成人精品| 日韩性生活视频| 亚洲不卡在线播放| 欧美一区影院| 久久久久成人网| 日韩美女一级片| 国产精品婷婷| 国产精品嫩草视频| 一二三四区在线| 精品一区二区三区免费观看| 91久久精品久久国产性色也91| 国产欧美日韩综合精品一区二区三区| 韩国午夜理伦三级不卡影院| 亚洲最大成人免费视频| www.五月天激情| 丁香婷婷综合激情五月色| 黄色小网站91| 欧美成人免费| 椎名由奈av一区二区三区| 肉大捧一出免费观看网站在线播放 | 影音先锋中文在线视频| 亚洲影院理伦片| 日韩av一二三四区| 欧美成人福利| 欧美α欧美αv大片| 一出一进一爽一粗一大视频| 激情综合网五月| 欧美成人在线网站| 国产性猛交╳xxx乱大交| 蜜臀av一区二区| 97超碰人人看人人 | 国产一区二区在线视频播放| 亚洲一区站长工具| 欧美福利视频一区| 亚洲天堂2024| **女人18毛片一区二区| 91精品国产99久久久久久| 亚洲无码精品一区二区三区| 国产麻豆午夜三级精品| 精品综合久久| 国产黄大片在线观看画质优化| 精品久久久中文| 羞羞的视频在线| 日本久久成人网| 久久av红桃一区二区小说| 久久亚洲天堂网| 国产主播一区二区| 欧美精品二区三区四区免费看视频| 免费观看成人高潮| 日韩欧美中文字幕在线观看| 黄色片免费网址| 亚洲丁香日韩| 久久久久久久97| 国产又大又粗又硬| 国产偷v国产偷v亚洲高清| 日本中文字幕在线视频观看| 国产精品99| 亚洲美女性视频| 久久亚洲精品大全| 精品一区二区免费视频| 欧美国产一区二区在线| 男女羞羞视频在线观看| 欧美三片在线视频观看| 日本xxx在线播放| 欧美精品日韩| 96国产粉嫩美女| youjizz在线播放| 色综合天天综合网国产成人综合天 | 国产黄人亚洲片| 亚洲成人18| 日韩久久一区二区三区| 精品视频在线播放| 精品少妇theporn| 国产精品综合二区| 在线观看一区二区三区三州| 成人全视频在线观看在线播放高清 | 国产福利在线观看| 欧美色视频日本版| 性久久久久久久久久久| 亚洲二区免费| 粉嫩高清一区二区三区精品视频 | 97视频在线观看免费| 亚洲乱码精品久久久久..| 亚洲欧洲99久久| 欧美成人手机在线视频| 国产精品精品| 91丝袜美腿美女视频网站| 五月婷婷在线视频| 欧美日本在线播放| 2017亚洲天堂| 韩国精品在线观看| 欧美a级黄色大片| 日韩一区二区三区色| 欧美精品在线观看91| jizz中国少妇| 亚洲福利视频一区二区| 精品视频站长推荐| 亚洲一区国产| 茄子视频成人在线观看| 日本h片久久| 夜夜嗨av色一区二区不卡| 中文字幕av资源| 综合分类小说区另类春色亚洲小说欧美| 亚洲欧美aaa| 午夜欧美理论片| 国产一区精品在线| 五月天国产在线| 宅男66日本亚洲欧美视频| 中文字幕在线观看1| 亚洲欧美一区二区在线观看| 国产在线视频三区| 亚洲国产综合在线看不卡| 国内一区二区三区在线视频| 亚洲一区资源| 日韩一区二区久久久| 国产夫绿帽单男3p精品视频| 午夜精品久久久久久| 亚洲精品乱码久久久久久久久久久久 | 久久亚洲一区二区三区四区五区高 | 日韩精品国产精品| 91社在线播放| 欧美黑人做爰爽爽爽| 国产精品福利观看| 污片视频在线免费观看| 精品亚洲国产视频| 一卡二卡三卡在线观看| 亚洲一二三四在线| 国产一二三四区在线| 国产69精品久久777的优势| 无码aⅴ精品一区二区三区浪潮| 成人三级视频| 国产伦精品一区二区三区高清版 | 国产视色精品亚洲一区二区| 播放一区二区| 久久99热精品| 国产裸舞福利在线视频合集| 日韩一区二区免费高清| 狠狠人妻久久久久久综合| 亚洲精品一二三区| 精品无码国产污污污免费网站| 久久se精品一区精品二区| 女人和拘做爰正片视频| 亚洲欧美偷拍自拍| 日韩一区免费观看| 电影一区二区在线观看| 国产在线播放91| 欧美18—19sex性hd| 欧美精品videosex极品1| 91社区在线| 日韩精品亚洲元码| www.国产三级| 欧美日韩精品是欧美日韩精品| 亚洲天堂日韩av| 亚洲乱码国产乱码精品精的特点| 国产黄色网址在线观看| 成人av网站在线观看| 亚洲欧美一区二区三区不卡| 日本aⅴ免费视频一区二区三区| 国产免费观看高清视频| 欧美日韩国产亚洲一区| 这里只有精品66| 精品免费视频| 日本高清一区| 美女视频亚洲色图| 成人黄色在线免费观看| 色成人综合网| 国产精品视频色| yy6080久久伦理一区二区| 日本欧美精品在线| 亚洲天堂导航| 欧美在线视频导航| 美女网站在线看| 韩国精品久久久999| 男人添女人下部高潮视频在线观看| 俺去啦;欧美日韩| www.亚洲资源| 国产一区二区三区久久精品 | 午夜电影一区| 亚洲自拍在线观看| 精品一区二区三区中文字幕| 成人中文字幕+乱码+中文字幕| 国产经典一区| 国产免费观看久久黄| 国产精品美女午夜爽爽| 国产精品视频自拍| 色999久久久精品人人澡69| 国产日韩精品在线观看| 青草综合视频| 亚洲一区亚洲二区亚洲三区| 国产精品国产三级在线观看| 亚洲精品欧美极品| 国产成人高清精品免费5388| 国产精品v欧美精品∨日韩| 开心激情综合| 欧美高清视频一区| 日韩一区二区三区免费播放| 一区二区精品视频| 中文精品久久| 草b视频在线观看| 久久亚洲视频| 亚洲视频一二三四| 国产福利91精品一区| 丰满岳乱妇一区二区| www成人在线观看| 人妻一区二区视频| 亚洲视频网在线直播| 青春草免费视频| 天天操天天色综合| 亚洲视屏在线观看| 欧美一区二区视频在线观看2020 | 国产伦精品一区二区三区视频痴汉| 777久久久精品| 国产 欧美 精品| 亚洲图片制服诱惑| 蜜桃av在线免费观看| 欧美日韩国产999| 天堂资源在线| 成人免费看吃奶视频网站| 国产精品qvod| 亚洲欧美日韩国产成人综合一二三区| 天天做天天爱天天爽综合网| 久久手机在线视频| 香蕉av777xxx色综合一区| www亚洲成人| 丁香一区二区三区| 一级黄色毛毛片| 亚洲国产综合视频在线观看| 手机av免费观看| 日韩一级高清毛片| 男人的天堂在线视频| 精品国产拍在线观看| 国模私拍视频在线播放| 欧洲亚洲免费视频| 精品国产亚洲一区二区在线观看| 久久精品国产一区二区三区日韩 | 天天做夜夜做人人爱精品| 亚洲国产精品一区二区第四页av| 午夜精品久久久久99热蜜桃导演| 日本va中文字幕| 高潮精品一区videoshd| 极品蜜桃臀肥臀-x88av| 亚洲电影中文字幕在线观看| 国产99久久久久久免费看| 日韩精品一区在线观看| 国产露出视频在线观看| 欧美劲爆第一页| 精品国产不卡一区二区| 日本福利一区二区三区| 99国产精品自拍| 亚洲欧美一区二区三区不卡| 国产亚洲欧美激情| 日韩免费在线视频观看| 制服.丝袜.亚洲.另类.中文 | 欧美中文一区| 91免费版看片| 久久国产精品99精品国产| 男生草女生视频| 亚洲成a人片综合在线| 国产精品福利电影| 一区二区亚洲精品国产| 欧美激情喷水| 久久av一区二区| 尤物在线精品| 日本少妇激三级做爰在线| 国产精品久久久久久久久动漫 | 久久99久久99精品免观看软件| 国外成人免费视频| 亚洲免费精品| 久久久久久婷婷| 亚洲一区国产视频| 精品国产av鲁一鲁一区| 美女国内精品自产拍在线播放| 国产精品4hu.www| 亚洲午夜精品一区二区| 日本美女一区二区三区| 精品欧美一区二区久久久| 日韩欧美中文在线| 国产一二三在线观看| 欧美中文字幕视频| 亚洲精品动态| 中文字幕日本最新乱码视频| 91视频国产资源| 国产精品第5页| 亚洲最新av在线| 福利一区二区免费视频| 亚洲激情啪啪| 久久99久久99小草精品免视看| 午夜激情福利电影| 欧美一区二区视频观看视频| 国产视频一区二区| 91久久爱成人| 黑人一区二区| xxxxxx黄色| 日韩欧美在线字幕| 啊v在线视频| 亚洲精品欧美日韩专区| 欧美特黄一区| 中文人妻一区二区三区| 欧洲一区二区三区在线| 免费看a在线观看| 91九色对白| 亚洲人成免费| 手机免费看av| 欧美精品一卡二卡| 在线观看三级视频| 久精品国产欧美| 日韩精品五月天| 欧美h片在线观看| 日韩欧美色电影| 亚洲一区站长工具| 艳母动漫在线免费观看| 国产.欧美.日韩| 国产污视频网站| 久久夜色精品国产亚洲aⅴ| 6080亚洲理论片在线观看| 干日本少妇首页| 国产精品理伦片| 国产 欧美 自拍| 国产精品高潮呻吟久久av无限| 一区二区电影在线观看| 一级少妇精品久久久久久久| 色综合天天综合| a级毛片免费观看在线| 久久影院理伦片| 久久国产剧场电影| 伊人国产在线观看| 伊人久久大香线蕉av一区二区| 免费欧美网站| 99草草国产熟女视频在线| 亚洲人成网站在线| 日批免费在线观看| 国产精品视频免费在线| 亚洲精品男同| 麻豆天美蜜桃91| 亚洲精品综合精品自拍| 电影一区中文字幕| 99精品免费在线观看| 亚洲在线观看免费| 午夜伦全在线观看| 久久青青草综合| 国产成人免费xxxxxxxx|