日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

虛擬內(nèi)存管理回顧

在 linux 操作系統(tǒng)中,虛擬地址空間的內(nèi)部又被分為內(nèi)核空間和用戶空間兩部分,不同位數(shù)的系統(tǒng),地址空間的范圍也不同。比如最常見的 32 位和 64 位系統(tǒng),如下所示:

 

通過這里可以看出:

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

再來說說,內(nèi)核空間與用戶空間的區(qū)別:

  • 進程在用戶態(tài)時,只能訪問用戶空間內(nèi)存;
  • 只有進入內(nèi)核態(tài)后,才可以訪問內(nèi)核空間的內(nèi)存;

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

 

我們看看用戶空間分布的情況,以 32 位系統(tǒng):

 

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

  • 0x0000 0000 到 0x0804 8000 這段虛擬內(nèi)存地址是一段不可訪問的保留區(qū),因為在大多數(shù)操作系統(tǒng)中,數(shù)值比較小的地址通常被認(rèn)為不是一個合法的地址,這塊小地址是不允許訪問的。比如在 C 語言中我們通常會將一些無效的指針設(shè)置為 NULL,指向這塊不允許訪問的地址。
  • 代碼段,包括二進制可執(zhí)行代碼;
  • 數(shù)據(jù)段,包括已初始化的靜態(tài)常量和全局變量;
  • BSS 段,包括未初始化的靜態(tài)變量和全局變量;
  • 堆段,包括動態(tài)分配的內(nèi)存,從低地址開始向上增長;
  • 堆空間的上邊是一段待分配區(qū)域,用于擴展堆空間的使用
  • 文件映射段,包括動態(tài)庫、共享內(nèi)存等,從低地址開始向上增長
  • 棧段,包括局部變量和函數(shù)調(diào)用的上下文等。棧的大小是固定的,一般是 8 MB。當(dāng)然系統(tǒng)也提供了參數(shù),以便我們自定義大小;

申請內(nèi)存的兩種方式

申請內(nèi)存空間一般就兩種方法,一種是malloc,另一種是 mmap映射空間。 在使用malloc()分配內(nèi)存的時候,可能系統(tǒng)調(diào)用brk(),也可能調(diào)用mmap()。

malloc的調(diào)用規(guī)律

1. 即分配一塊小型內(nèi)存(小于或等于128kb),malloc()會調(diào)用brk 函數(shù)將 堆頂 指針向高地址移動,獲得新的內(nèi)存空間。

2. 當(dāng)分配一塊大型內(nèi)存(大于128kb),mmap() 系統(tǒng)調(diào)用中「私有匿名映射」的方式,在文件映射區(qū)分配一塊內(nèi)存

申請內(nèi)存過程圖

 

需要注意的是,malloc() 分配的是虛擬內(nèi)存

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

只有在訪問已分配的虛擬地址空間的時候,操作系統(tǒng)通過查找頁表,發(fā)現(xiàn)虛擬內(nèi)存對應(yīng)的頁沒有在物理內(nèi)存中,就會觸發(fā)缺頁中斷,然后操作系統(tǒng)會建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系。

缺頁中斷就是要訪問的頁不在主存,需要操作系統(tǒng)將其調(diào)入主存后再進行訪問。在這個時候,被內(nèi)存映射的文件實際上成了一個分頁交換文件。

malloc 申請的內(nèi)存,free 釋放內(nèi)存會歸還給操作系統(tǒng)嗎

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

mmap 和 brk 分配內(nèi)存的區(qū)別

mmap 來分配內(nèi)存的問題

mmap 分配的內(nèi)存每次釋放的時候,都會歸還給操作系統(tǒng),于是每次 mmap 分配的虛擬地址都是缺頁狀態(tài)的,然后在第一次訪問該虛擬地址的時候,就會觸發(fā)缺頁中斷。

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

為了改進這兩個問題,malloc 通過 brk() 系統(tǒng)調(diào)用在堆空間申請內(nèi)存的時候,由于堆空間是連續(xù)的,所以直接預(yù)分配更大的內(nèi)存來作為內(nèi)存池,當(dāng)內(nèi)存釋放的時候,就緩存在內(nèi)存池中。

等下次在申請內(nèi)存的時候,就直接從內(nèi)存池取出對應(yīng)的內(nèi)存塊就行了,而且可能這個內(nèi)存塊的虛擬地址與物理地址的映射關(guān)系還存在,這樣不僅減少了系統(tǒng)調(diào)用的次數(shù),也減少了缺頁中斷的次數(shù),這將大大降低 CPU 的消耗

只使用 brk 來分配內(nèi)存的問題

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

如果我們連續(xù)申請了 10k,20k,30k 這三片內(nèi)存,如果 10k 和 20k 這兩片釋放了,變?yōu)榱丝臻e內(nèi)存空間,如果下次申請的內(nèi)存小于 30k,那么就可以重用這個空閑內(nèi)存空間。

 

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

因此,隨著系統(tǒng)頻繁地 malloc 和 free ,尤其對于小塊內(nèi)存,堆內(nèi)將產(chǎn)生越來越多不可用的碎片,導(dǎo)致“內(nèi)存泄露”。而這種“泄露”現(xiàn)象使用 valgrind 是無法檢測出來的。

所以,malloc 實現(xiàn)中,充分考慮了 brk 和 mmap 行為上的差異及優(yōu)缺點,默認(rèn)分配大塊內(nèi)存 (128KB) 才使用 mmap 分配內(nèi)存空間。

分享到:
標(biāo)簽:linux
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達(dá)人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定