內(nèi)存分配(malloc)的過程

[TOC]

參考

  1. malloc()之后挺益,內(nèi)核發(fā)生了什么糠溜?
  2. 進(jìn)程分配內(nèi)存的兩種方式--brk() 和mmap()(不涉及共享內(nèi)存)
  3. Linux內(nèi)存分配小結(jié)--malloc正驻、brk劲藐、mmap
  4. 詳解缺頁中斷-----缺頁中斷處理(內(nèi)核锌钮、用戶)

本文主要摘抄自進(jìn)程分配內(nèi)存的兩種方式--brk() 和mmap()(不涉及共享內(nèi)存)

1. 缺頁中斷

1.1. 什么是缺頁中斷

malloc和mmap等內(nèi)存分配函數(shù)只是建立進(jìn)程的虛擬地址空間告希,并沒有分配實際的物理內(nèi)存耀态。當(dāng)進(jìn)程訪問沒有建立映射關(guān)系的虛擬內(nèi)存時會自動的觸發(fā)一個缺頁中斷。

請求分頁的系統(tǒng)當(dāng)中暂雹,可以查詢頁表當(dāng)前的狀態(tài)位來查詢當(dāng)前頁是否在內(nèi)存當(dāng)中首装,如果不在內(nèi)存當(dāng)中可以通過頁表當(dāng)中的外存地址將缺的一頁讀到內(nèi)存當(dāng)中。比如mmap映射文件杭跪。

1.2. 如何查看缺頁中斷

ps -o majflt,minflt -C program命令查看仙逻。

majflt代表major fault(需要讀取磁盤),中文名叫大錯誤涧尿,minflt代表minor fault(不需要讀取磁盤)系奉,中文名叫小錯誤。

這兩個數(shù)值表示一個進(jìn)程自啟動以來所發(fā)生的缺頁中斷的次數(shù)姑廉。

1.3. 缺頁異常發(fā)生后的操作

當(dāng)一個進(jìn)程發(fā)生缺頁中斷的時候缺亮,進(jìn)程會陷入內(nèi)核態(tài),執(zhí)行以下操作:

  1. 檢查要訪問的虛擬地址是否合法
  2. 查找/分配一個物理頁
  3. 填充物理頁內(nèi)容(讀取磁盤桥言,或者直接置0萌踱,或者啥也不干)
  4. 建立映射關(guān)系(虛擬地址到物理地址)
  5. 重新執(zhí)行發(fā)生缺頁中斷的那條指令

如果第3步葵礼,需要讀取磁盤,那么這次缺頁中斷就是majflt并鸵,否則就是minflt鸳粉。

2. 內(nèi)存分配過程(malloc)

從操作系統(tǒng)角度來看,進(jìn)程分配內(nèi)存有兩種方式园担,分別由兩個系統(tǒng)調(diào)用完成:brk和mmap(不考慮共享內(nèi)存)届谈。

  1. brk是將數(shù)據(jù)段(.data)的最高地址指針_edata往高地址推;

  2. mmap是在進(jìn)程的虛擬地址空間中(堆和棧中間弯汰,稱為文件映射區(qū)域的地方)找一塊空閑的虛擬內(nèi)存艰山。

這兩種方式分配的都是虛擬內(nèi)存,沒有分配物理內(nèi)存咏闪。在第一次訪問(讀/寫)已分配的虛擬地址空間的時候曙搬,發(fā)生缺頁中斷,操作系統(tǒng)負(fù)責(zé)分配物理內(nèi)存汤踏,然后建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系织鲸。

在標(biāo)準(zhǔn)C庫中舔腾,提供了malloc/free函數(shù)分配釋放內(nèi)存溪胶,這兩個函數(shù)底層是由brk,mmap稳诚,munmap這些系統(tǒng)調(diào)用實現(xiàn)的哗脖。

2.1. brk分配

malloc小于128k的內(nèi)存,使用brk分配內(nèi)存扳还,將_edata往高地址推

brk分配內(nèi)存
  1. 進(jìn)程啟動的時候才避,其(虛擬)內(nèi)存空間的初始布局如圖1所示。其中氨距,mmap內(nèi)存映射文件是在堆和棧的中間(例如libc-2.2.93.so桑逝,其它數(shù)據(jù)文件等),為了簡單起見俏让,省略了內(nèi)存映射文件楞遏。_edata指針(glibc里面定義)指向數(shù)據(jù)段的最高地址。
  2. 進(jìn)程調(diào)用A=malloc(30K)以后首昔,內(nèi)存空間如圖2:malloc函數(shù)會調(diào)用brk系統(tǒng)調(diào)用寡喝,將_edata指針往高地址推30K,就完成虛擬內(nèi)存分配勒奇。(注:_edata+30K只是完成虛擬地址的分配预鬓,A這塊內(nèi)存現(xiàn)在還是沒有物理頁與之對應(yīng)的,等到進(jìn)程第一次讀寫A這塊內(nèi)存的時候赊颠,發(fā)生缺頁中斷格二,這個時候劈彪,內(nèi)核才分配A這塊內(nèi)存對應(yīng)的物理頁。也就是說蟋定,如果用malloc分配了A這塊內(nèi)容粉臊,然后從來不訪問它,那么驶兜,A對應(yīng)的物理頁是不會被分配的扼仲。)
  3. 進(jìn)程調(diào)用B=malloc(40K)以后,內(nèi)存空間如圖3抄淑。

2.2. mmap分配內(nèi)存

malloc大于128k的內(nèi)存屠凶,使用mmap分配內(nèi)存,在堆和棧之間找一塊空閑內(nèi)存分配(對應(yīng)獨立內(nèi)存肆资,而且初始化為0)


mmap分配內(nèi)存
  1. 進(jìn)程調(diào)用C=malloc(200K)以后矗愧,內(nèi)存空間如圖4:默認(rèn)情況下,malloc函數(shù)分配內(nèi)存郑原,如果請求內(nèi)存大于128K(可由M_MMAP_THRESHOLD選項調(diào)節(jié))唉韭,那就不是去推_edata指針了,而是利用mmap系統(tǒng)調(diào)用犯犁,從堆和棧的中間分配一塊虛擬內(nèi)存属愤。
    這樣子做主要是因為:brk分配的內(nèi)存需要等到高地址內(nèi)存釋放以后才能釋放(例如,在B釋放之前酸役,A是不可能釋放的住诸,這就是內(nèi)存碎片產(chǎn)生的原因,什么時候緊縮看下面)涣澡,而mmap分配的內(nèi)存可以單獨釋放贱呐。
  2. 進(jìn)程調(diào)用D=malloc(100K)以后,內(nèi)存空間如圖5入桂;
  3. 進(jìn)程調(diào)用free(C)以后奄薇,C對應(yīng)的虛擬內(nèi)存和物理內(nèi)存一起釋放。

2.3. 釋放內(nèi)存

上一小節(jié)已經(jīng)介紹了mmap的內(nèi)存釋放抗愁,這里主要看brk的內(nèi)存釋放


釋放內(nèi)存
  1. 進(jìn)程調(diào)用free(B)以后馁蒂,如圖7所示:B對應(yīng)的虛擬內(nèi)存和物理內(nèi)存都沒有釋放,因為只有一個_edata指針驹愚,如果往回推远搪,那么D這塊內(nèi)存怎么辦呢?當(dāng)然逢捺,B這塊內(nèi)存谁鳍,是可以重用的,如果這個時候再來一個40K的請求,那么malloc很可能就把B這塊內(nèi)存返回回去了倘潜。
  2. 進(jìn)程調(diào)用free(D)以后绷柒,如圖8所示:B和D連接起來,變成一塊140K的空閑內(nèi)存涮因。
  3. 默認(rèn)情況下:當(dāng)最高地址空間的空閑內(nèi)存超過128K(可由M_TRIM_THRESHOLD選項調(diào)節(jié))時废睦,執(zhí)行內(nèi)存緊縮操作(trim)。在上一個步驟free的時候养泡,發(fā)現(xiàn)最高地址空閑內(nèi)存超過128K嗜湃,于是內(nèi)存緊縮,變成圖9所示澜掩。

3. malloc 測試

  • 循環(huán)new分配64K * 2048的內(nèi)存空間购披,寫入臟數(shù)據(jù)后,循環(huán)調(diào)用delete釋放肩榕。top看進(jìn)程依然使用131M內(nèi)存刚陡,沒有釋放。 —— 此時用brk
  • 循環(huán)new分配128K * 2048的內(nèi)存空間株汉,寫入臟數(shù)據(jù)后筐乳,循環(huán)調(diào)用delete釋放。top看進(jìn)程使用乔妈,2960字節(jié)內(nèi)存蝙云,完全釋放。 —— 此時用mmap
  • 設(shè)置M_MMAP_THRESHOLD 256k褒翰,循環(huán)new分配128k * 2048 的內(nèi)存空間贮懈,寫入臟數(shù)據(jù)后匀泊,循環(huán)調(diào)用delete釋放优训,而后調(diào)用malloc_trim(0)。top看進(jìn)程使用各聘,2348字節(jié)揣非,完全釋放。 ——此時用brk

4. 簡單思考

既然堆內(nèi)內(nèi)存brk不能直接釋放躲因,為什么不全部使用 mmap 來分配早敬,munmap直接釋放呢?
其實,進(jìn)程向 OS 申請和釋放地址空間的接口 sbrk/mmap/munmap 都是系統(tǒng)調(diào)用大脉,頻繁調(diào)用系統(tǒng)調(diào)用都比較消耗系統(tǒng)資源的搞监。并且, mmap 申請的內(nèi)存被 munmap 后镰矿,重新申請會產(chǎn)生更多的缺頁中斷琐驴。例如使用 mmap 分配 1M 空間,第一次調(diào)用產(chǎn)生了大量缺頁中斷 (1M/4K 次 ) ,當(dāng)munmap 后再次分配 1M 空間绝淡,會再次產(chǎn)生大量缺頁中斷宙刘。缺頁中斷是內(nèi)核行為,會導(dǎo)致內(nèi)核態(tài)CPU消耗較大牢酵。另外悬包,如果使用 mmap 分配小內(nèi)存,會導(dǎo)致地址空間的分片更多馍乙,內(nèi)核的管理負(fù)擔(dān)更大布近。
同時堆是一個連續(xù)空間,并且堆內(nèi)碎片由于沒有歸還 OS 丝格,如果可重用碎片吊输,再次訪問該內(nèi)存很可能不需產(chǎn)生任何系統(tǒng)調(diào)用和缺頁中斷,這將大大降低 CPU 的消耗铁追。 因此季蚂, glibc 的 malloc 實現(xiàn)中,充分考慮了 brk 和 mmap 行為上的差異及優(yōu)缺點琅束,默認(rèn)分配大塊內(nèi)存 (128k) 才使用 mmap 獲得地址空間扭屁,也可通過 mallopt(M_MMAP_THRESHOLD, <SIZE>) 來修改這個臨界值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涩禀,一起剝皮案震驚了整個濱河市料滥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌艾船,老刑警劉巖葵腹,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屿岂,居然都是意外死亡践宴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門爷怀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阻肩,“玉大人,你說我怎么就攤上這事运授】揪” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵吁朦,是天一觀的道長柒室。 經(jīng)常有香客問我,道長逗宜,這世上最難降的妖魔是什么雄右? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任剥啤,我火速辦了婚禮,結(jié)果婚禮上不脯,老公的妹妹穿的比我還像新娘府怯。我一直安慰自己,他們只是感情好防楷,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布牺丙。 她就那樣靜靜地躺著,像睡著了一般复局。 火紅的嫁衣襯著肌膚如雪冲簿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天亿昏,我揣著相機(jī)與錄音峦剔,去河邊找鬼。 笑死角钩,一個胖子當(dāng)著我的面吹牛吝沫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播递礼,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼惨险,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了脊髓?” 一聲冷哼從身側(cè)響起辫愉,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎将硝,沒想到半個月后恭朗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡依疼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年痰腮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涛贯。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡诽嘉,死狀恐怖蔚出,靈堂內(nèi)的尸體忽然破棺而出弟翘,到底是詐尸還是另有隱情,我是刑警寧澤骄酗,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布稀余,位于F島的核電站,受9級特大地震影響趋翻,放射性物質(zhì)發(fā)生泄漏睛琳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望师骗。 院中可真熱鬧历等,春花似錦、人聲如沸辟癌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黍少。三九已至寡夹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厂置,已是汗流浹背菩掏。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留昵济,地道東北人智绸。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像访忿,于是被迫代替她去往敵國和親传于。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容