歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux Slub分配器

Slab分配器一直處於內核內存管理的核心地位,盡管如此,它還是擁有自身的缺點,最明顯的兩點就是復雜性和過多的管理數據造成的內存上的開銷。針對這些問題,linux引入了slub分配器,slub分配器保留了slab分配器的所有接口,實際上slub分配器的模型和slab分配的模型是基本一致的,只不過在一些地方進行了精簡,這也使得slub分配器工作起來更為游刃有余。兩者主要的區別如下:
  • slab分配器為了增加分配速度,引入了一些管理數組,如slab管理區中的kmem_bufctl數組和緊隨本地CPU結構後面的用來跟蹤最熱空閒對象的數組,這些結構雖然加快了分配對象的速度,但也增加了一定的復雜性,而且隨著系統變得龐大,其對內存的開銷也越明顯。而slub分配器則完全摒棄了這些管理數據,個人覺得這也是slub分配器最精髓的地方,至於slub分配器的具體做法是怎樣的,後面再做分析;
  • slab分配器針對每個緩存,根據slab的狀態劃分了3個鏈表--full,partial和free. slub分配器做了簡化,去掉了free鏈表,對於空閒的slab,slub分配器選擇直接將其釋放;
  • slub分配器摒棄了slab分配器中的著色概念,在slab分配器中,由於顏色的個數有限,因此著色也無法完全解決slab之間的緩存行沖突問題,考慮到著色造成了內存上的浪費,slub分配器沒有引入著色;
  • 在NUMA架構的支持上,slub分配器也較slab分配器做了簡化。

下面來看slub分配器涉及到的主要數據結構

緩存描述結構:

  1. struct kmem_cache {  
  2.     /* Used for retriving partial slabs etc */  
  3.     unsigned long flags; /* cache屬性的描述標識 */  
  4.     int size;        /* 分配給對象的內存大小,可能大於實際對象的大小 */  
  5.     int objsize;         /* 對象的實際大小 */    
  6.     int offset;          /* 存放空閒對象的偏移,以字節為單位 */  
  7.     struct kmem_cache_order_objects oo;/* oo用來存放分配給slab的頁框的階數(高16位)和 
  8.                                                 slab中的對象數量(低16位) */  
  9.   
  10.     /* 
  11.      * Avoid an extra cache line for UP, SMP and for the node local to 
  12.      * struct kmem_cache. 
  13.      */  
  14.     struct kmem_cache_node local_node;/* 本地節點的slab信息 */  
  15.   
  16.     /* Allocation and freeing of slabs */  
  17.     struct kmem_cache_order_objects max;  
  18.     struct kmem_cache_order_objects min;  
  19.     gfp_t allocflags;      /* 分配時用的GFP標識 */  
  20.     int refcount;          /* 緩存中存在的對象種類數目,因為slub允許緩存復用, 
  21.                                   因此一個緩存中可能存在多種對象類型 */  
  22.     void (*ctor)(void *);  /* 創建對象的構造函數 */  
  23.     int inuse;             /* 元數據的偏移 */  
  24.     int align;         /* 對齊值 */  
  25.     unsigned long min_partial;/* partial slab鏈表中的最小slab數目 */  
  26.     const char *name;     /* 緩存名 */  
  27.     struct list_head list;    /* 用於將緩存鏈入slab_caches全局緩存鏈表 */  
  28. #ifdef CONFIG_SLUB_DEBUG   
  29.     struct kobject kobj;      /* For sysfs */  
  30. #endif   
  31.   
  32. #ifdef CONFIG_NUMA   
  33.     /* 
  34.      * Defragmentation by allocating from a remote node. 
  35.      */  
  36.     int remote_node_defrag_ratio;   /* 該值越小,越傾向於從本節點分配對象 */  
  37.     struct kmem_cache_node *node[MAX_NUMNODES];/* NUMA架構下每個節點對應的slab信息 */  
  38. #endif   
  39. #ifdef CONFIG_SMP   
  40.     struct kmem_cache_cpu *cpu_slab[NR_CPUS];  /* SMP系統下每個CPU對應的slab信息 */  
  41. #else   
  42.     struct kmem_cache_cpu cpu_slab; /* 單核系統下CPU對應的slab信息 */  
  43. #endif   
  44. };  

節點的slab信息描述結構:

  1. struct kmem_cache_node {  
  2.     spinlock_t list_lock;       /* Protect partial list and nr_partial */  
  3.     unsigned long nr_partial;   /* partial slab鏈表中slab的數量 */  
  4.     struct list_head partial;   /* partial slab鏈表表頭*/  
  5. #ifdef CONFIG_SLUB_DEBUG   
  6.     atomic_long_t nr_slabs;      /* 節點中的slab數 */  
  7.     atomic_long_t total_objects; /* 節點中的對象數 */  
  8.     struct list_head full;       /* full slab鏈表表頭 */  
  9. #endif   
  10. }; 

本地CPU的slab信息描述結構:

  1. struct kmem_cache_cpu {  
  2.     void **freelist;    /* 指向本地CPU的第一個空閒對象 */  
  3.     struct page *page;  /* 分配給本地CPU的slab的頁框 */  
  4.     int node;           /* 頁框所處的節點,值為-1時表示DEBUG */  
  5.     unsigned int offset;    /* 空閒對象指針的偏移,以字長為單位 */  
  6.     unsigned int objsize;   /* 對象的大小 */  
  7. #ifdef CONFIG_SLUB_STATS   
  8.     unsigned stat[NR_SLUB_STAT_ITEMS];/*用以記錄slab的狀態*/  
  9. #endif   
  10. }; 

用下圖可以描述這些slub分配器的核心數據結構之間的關系

 

至此已大概介紹了slub分配器的一些概念和涉及到的核心數據結構,具體的實現細節和原理在後面分析各個部分的代碼時再做交代!

Copyright © Linux教程網 All Rights Reserved