自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux頁框分配器之內(nèi)存碎片化整理

系統(tǒng) Linux
Linux內(nèi)存對碎片化的整理算法主要應用了內(nèi)核的頁面遷移機制,是一種將可移動頁面進行遷移后騰出連續(xù)物理內(nèi)存的方法。

[[357683]]

本文轉(zhuǎn)載自微信公眾號「人人都是極客」,作者布道師Peter 。轉(zhuǎn)載本文請聯(lián)系人人都是極客公眾號。 

頁框分配器在慢速分配中包括內(nèi)存碎片化整理和內(nèi)存回收,代碼如下:

  1. static inline struct page * 
  2. __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order
  3.       struct alloc_context *ac) 
  4.   page = __alloc_pages_direct_compact(gfp_mask, order,  
  5.       alloc_flags, ac, 
  6.       INIT_COMPACT_PRIORITY, 
  7.       &compact_result); 
  8.   ...... 
  9.   page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,  
  10.        &did_some_progress); 
  11.   ...... 

出于篇幅設計,這次我們只講內(nèi)存的碎片化整理,下文再講內(nèi)存回收。

什么是內(nèi)存碎片化

Linux物理內(nèi)存碎片化包括兩種:內(nèi)部碎片化和外部碎片化。

內(nèi)部碎片化:

指分配給用戶的內(nèi)存空間中未被使用的部分。例如進程需要使用3K bytes物理內(nèi)存,于是向系統(tǒng)申請了大小等于3Kbytes的內(nèi)存,但是由于Linux內(nèi)核伙伴系統(tǒng)算法最小顆粒是4K bytes,所以分配的是4Kbytes內(nèi)存,那么其中1K bytes未被使用的內(nèi)存就是內(nèi)存內(nèi)碎片。

外部碎片化:

指系統(tǒng)中無法利用的小內(nèi)存塊。例如系統(tǒng)剩余內(nèi)存為16K bytes,但是這16K bytes內(nèi)存是由4個4K bytes的頁面組成,即16K內(nèi)存物理頁幀號#1不連續(xù)。在系統(tǒng)剩余16K bytes內(nèi)存的情況下,系統(tǒng)卻無法成功分配大于4K的連續(xù)物理內(nèi)存,該情況就是內(nèi)存外碎片導致。

碎片化整理算法

Linux內(nèi)存對碎片化的整理算法主要應用了內(nèi)核的頁面遷移機制,是一種將可移動頁面進行遷移后騰出連續(xù)物理內(nèi)存的方法。

假設存在一個非常小的內(nèi)存域如下:

藍色表示空閑的頁面,白色表示已經(jīng)被分配的頁面,可以看到如上內(nèi)存域的空閑頁面(藍色)非常零散,無法分配大于兩頁的連續(xù)物理內(nèi)存。

下面演示一下內(nèi)存規(guī)整的簡化工作原理,內(nèi)核會運行兩個獨立的掃描動作:第一個掃描從內(nèi)存域的底部開始,一邊掃描一邊將已分配的可移動(MOVABLE)頁面記錄到一個列表中:

另外第二掃描是從內(nèi)存域的頂部開始,掃描可以作為頁面遷移目標的空閑頁面位置,然后也記錄到一個列表里面:

等兩個掃描在域中間相遇,意味著掃描結(jié)束,然后將左邊掃描得到的已分配的頁面遷移到右邊空閑的頁面中,左邊就形成了一段連續(xù)的物理內(nèi)存,完成頁面規(guī)整。

碎片化整理的三種方式

  1. static struct page * 
  2. __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order
  3.   unsigned int alloc_flags, const struct alloc_context *ac, 
  4.   enum compact_priority prio, enum compact_result *compact_result) 
  5.  struct page *page; 
  6.  unsigned int noreclaim_flag; 
  7.  
  8.  if (!order
  9.   return NULL
  10.  
  11.  noreclaim_flag = memalloc_noreclaim_save(); 
  12.  *compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac, 
  13.          prio); 
  14.  memalloc_noreclaim_restore(noreclaim_flag); 
  15.  
  16.  if (*compact_result <= COMPACT_INACTIVE) 
  17.   return NULL
  18.  
  19.  count_vm_event(COMPACTSTALL); 
  20.  
  21.  page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac); 
  22.  
  23.  if (page) { 
  24.   struct zone *zone = page_zone(page); 
  25.  
  26.   zone->compact_blockskip_flush = false
  27.   compaction_defer_reset(zone, ordertrue); 
  28.   count_vm_event(COMPACTSUCCESS); 
  29.   return page; 
  30.  } 
  31.  
  32.  count_vm_event(COMPACTFAIL); 
  33.  
  34.  cond_resched(); 
  35.  
  36.  return NULL

這也是上面memory compaction算法的代碼實現(xiàn)。

在linux內(nèi)核里一共有3種方式可以碎片化整理,我們總結(jié)如下:

這里就不展開源碼的解析了,有了宏觀的理解然后再去網(wǎng)上搜下具體實現(xiàn)細節(jié)相信不是什么難事,OK,我們進入下面的文章內(nèi)容:內(nèi)存回收(memory reclaim)。

 

責任編輯:武曉燕 來源: 人人都是極客
相關推薦

2013-10-12 11:15:09

Linux運維內(nèi)存管理

2023-04-03 08:25:02

Linux內(nèi)存slub

2021-08-03 09:02:58

LinuxSlab算法

2024-10-11 10:00:20

2009-12-25 15:34:54

slab分配器

2025-04-11 00:44:00

2024-12-11 08:18:11

2020-07-07 07:57:39

Linux內(nèi)存碎片化

2017-02-08 08:40:21

C++固定內(nèi)存塊

2017-01-17 16:17:48

C++固定分配器

2017-01-20 14:21:35

內(nèi)存分配器存儲

2020-03-11 13:44:20

編程語言PythonJava

2021-05-27 05:28:18

Linux 內(nèi)存管理

2022-02-23 16:49:19

Linux內(nèi)存數(shù)據(jù)結(jié)構(gòu)

2013-10-14 10:41:41

分配器buddy syste

2014-09-01 10:09:44

Linux

2025-02-10 07:30:00

malloc內(nèi)存分配器內(nèi)存

2023-12-22 07:55:38

Go語言分配策略

2024-10-28 11:25:21

豐巢快遞jemalloc

2023-04-13 14:42:26

PoE供電器PoE交換機
點贊
收藏

51CTO技術(shù)棧公眾號