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