內存管理之SLUB

kernel 3.10使用slub,不是slab
文件
Slub.c (android\kernel\mm)
Slab_common.c (android\kernel\mm)

-------全局變量和接口----------------
/*Slab cache management.*/
struct kmem_cache {
	struct kmem_cache_cpu __percpu *cpu_slab;   //每CPU變量,只保留一個slab,當沒有空閒內存的情況下才會從kmem_cache_node中換出其他的slab。
	
	/* Used for retriving partial slabs etc */
	unsigned long flags;
	unsigned long min_partial;
	int size;		/* The size of an object including meta data,meta data一般是個4字節的指針,用於指向下一個空閒的object,從而形成一個object的鏈表*/
	int object_size;	/* The size of an object without meta data , 該slab cache中的每個slab的大小,單位是字節 */
	int offset;		/* Free pointer offset. 重要,空閒的object的偏移量*/
	int cpu_partial;	/* Number of per cpu partial objects to keep around */
	struct kmem_cache_order_objects oo;

	/* Allocation and freeing of slabs */
	struct kmem_cache_order_objects max;
	struct kmem_cache_order_objects min;
	gfp_t allocflags;	/* gfp flags to use on each alloc */
	int refcount;		/* Refcount for slab cache destroy */
	void (*ctor)(void *);
	int inuse;		/* Offset to metadata */
	int align;		/* Alignment */
	int reserved;		/* Reserved bytes at the end of slabs */
	const char *name;	/* Name (only for display!) ,slab分配器的名字,一般會帶size的尾數,如“kmalloc-64” */
	struct list_head list;	/* List of slab caches , 用於將該slab分配器鏈入到鏈表slab_caches中*/
#ifdef CONFIG_SYSFS
	struct kobject kobj;	/* For sysfs */
#endif
	struct kmem_cache_node *node[MAX_NUMNODES];   //對於UMA系統,MAX_NUMNODES==0,即只有1個node
};

/* The slab lists for all objects.*/
struct kmem_cache_node {
	spinlock_t list_lock;
	
#ifdef CONFIG_SLUB
	unsigned long nr_partial;
	struct list_head partial;  //物理頁面部分滿(即物理頁面有空閒空間)的slab的 list
#ifdef CONFIG_SLUB_DEBUG
	atomic_long_t nr_slabs;
	atomic_long_t total_objects;
	struct list_head full;   //物理頁面全滿(即沒有空閒空間)的slab的 list
#endif
#endif
};

struct kmem_cache_cpu {
	void **freelist;	/* Pointer to next available object, 指向下一個空閒的object,即離page開始地址的偏移量 */
	unsigned long tid;	/* Globally unique transaction id */
	struct page *page;	/* The slab from which we are allocating, 是從哪個slab(即slab的某個page)中分配的object? */
	struct page *partial;	/* Partially allocated frozen slabs */
};

/* Maximum size for which we actually use a slab cache */
#define KMALLOC_MAX_CACHE_SIZE	(1UL << KMALLOC_SHIFT_HIGH(13))  //kmalloc時,如果要從slab中分配內存,最大能malloc的size,否則要從buddy system(page allocator)中去分配更多的page,見__kmalloc()


初始化:mm_init() -> kmem_cache_init()->create_kmalloc_caches()->create_kmalloc_cache()

struct kmem_cache *kmem_cache;  //

slab_caches  //存放所有的slab cache(即slab分配器)的list

struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH(12) + 1];  //預先創建好的slab分配器數組,數組的索引一般表示該slab分配器是隻含有2^index字節的slab(個別除外),見kmalloc_slab()

//分配kmem_cache型數據
kmem_cache_zalloc()
->kmem_cache_alloc()->slab_alloc()->slab_alloc_node()
{
	//如果需要分配新的物理頁面
	->__slab_alloc()->new_slab_objects()->new_slab()->allocate_slab()->alloc_slab_page()->alloc_pages()	
}

page->slab_cache = s;  //保存page 所屬的slab分配器
__SetPageSlab(page); //page->flags |= 1 << PG_slab; 爲頁框增加一個slab屬性.

page->freelist = start; //第一個free的object的地址
page->objects    //page中有多少object
page->inuse   //有多少使用了的??

struct page *mem_map;  //這是數組,存放所有的stuct page的信息

page->_count //頁的引用計數器。如果該字段爲-1,則相應頁框空閒,並可被分配給任一進程或內核本身;如果該字段的值大於或等於0,則說明頁框被分配給一個或多個進程,或用於存放一些內核數據結構。
//page_count()函數返回_count加1後的值,也就是該頁的使用者的數目。
//釋放
kfree()->slab_free()->set_freepointer()
------如何計算某個虛擬地址A對應的page的指針(虛擬地址)
/* pt A 找出A對應的物理地址PA */
或者是PA = A-0XC0000000+0X80000000(chip的memory map中的DDR的基地址)
2)算出物理地址的全局幀號 g_pfn=PA>>12位
  並獲得內存節點的起始幀號
  contig_page_data_=_(
    node_zones = ((watermark = (942, 2312, 2548), percpu_drift_mark = 0, lo
    node_zonelists = ((zlcache_ptr = 0x0 = , _zonerefs = ((zone = 0xC0FCA140 
    nr_zones = 1,
    node_mem_map = 0xC12B5000 = __bss_stop+0xC64,   //====>  ==mem_map的值
    bdata = 0xC0F03178 = bootmem_node_data,
    node_start_pfn = 0x00080000,   //=====>  node的起始幀號,這個是DDR的物理起始地址,見CHIP的memory map
    node_present_pages = 167680,
    node_spanned_pages = 195840,
    node_id = 0,
    reclaim_nodes = (bits = (0)),
    kswapd_wait = (lock = (rlock = (raw_lock = (slock = 5570645, tickets = (owner = 85, next = 85)))), 
    pfmemalloc_wait = (lock = (rlock = (raw_lock = (slock = 0, tickets = (owner = 0, next = 0)))), 
    kswapd = 0xE6959500 = __bss_stop+0x256A5164,
    kswapd_max_order = 0,
    classzone_idx = ZONE_NORMAL)

因此物理幀號在mem_map數組中的偏移爲:g_pfn-0x80000



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章