这节的内容主要讲解slab对象的分配与释放、及非连续内存区管理;虽然大部分都是代码,我感觉看代码更能理解这个执行的过程。
一、本地高速缓存
1、在高速缓存描述符中前三个元素,当创建一个slab告诉缓存时,kemem_cache_create()函数决定了本地高速缓存的大小(下面的第三个)、分配本地高速缓存,并将它们的指针存放在高速缓存描述符的array字段。这个大小取决于存放在slab高速缓存中对象的大小,范围1(相对于大对象)~120(相对于小对象);
struct kmem_cache_s {
/**
* 每CPU指针数组,指向包含空闲对象的本地高速缓存。
*/
struct array_cache *array[NR_CPUS];//NR_CPUS 为系统CPU个数
/**
* 要转移进本地高速缓存或从本地高速缓存中转移出的大批对象的数量。
*/
unsigned int batchcount;
/**
* 本地高速缓存中空闲对象的最大数目。这个参数可调。
*/
unsigned int limit;
...........
}
2、引进这个本地缓存主要是用来减少处理器之间对自旋锁的竞争并更好地利用硬件高速缓存,高速缓存描述符的array字段是一组指向array_cache数据结构的指针,系统中每一个cpu对应一个元素。
3、每个array_cache数据结构是空闲对象的本地缓存的一个描述符;
4、可以想一下每个cpu都有自己的本地缓存,用的时候直接取出会提高执行效率;
1、函数先试图从本地缓存获得一个空闲对象;
2、如果本地缓存没有空闲对象就调用cache_alloc_refill(cachep, flags)函数;
一、本地高速缓存
1、在高速缓存描述符中前三个元素,当创建一个slab告诉缓存时,kemem_cache_create()函数决定了本地高速缓存的大小(下面的第三个)、分配本地高速缓存,并将它们的指针存放在高速缓存描述符的array字段。这个大小取决于存放在slab高速缓存中对象的大小,范围1(相对于大对象)~120(相对于小对象);
struct kmem_cache_s {
/**
* 每CPU指针数组,指向包含空闲对象的本地高速缓存。
*/
struct array_cache *array[NR_CPUS];//NR_CPUS 为系统CPU个数
/**
* 要转移进本地高速缓存或从本地高速缓存中转移出的大批对象的数量。
*/
unsigned int batchcount;
/**
* 本地高速缓存中空闲对象的最大数目。这个参数可调。
*/
unsigned int limit;
...........
}
2、引进这个本地缓存主要是用来减少处理器之间对自旋锁的竞争并更好地利用硬件高速缓存,高速缓存描述符的array字段是一组指向array_cache数据结构的指针,系统中每一个cpu对应一个元素。
3、每个array_cache数据结构是空闲对象的本地缓存的一个描述符;
4、可以想一下每个cpu都有自己的本地缓存,用的时候直接取出会提高执行效率;
/**
* 空闲对象的本地高速缓存描述符(注意:是描述符而不是本地高速缓存本身,本地高速缓存在描述符后面)
*/
struct array_cache {
/**
* 指向本地高速缓存中可使用对象的指针的个数。
* 它同时也作为高速缓存中第一个空槽的下标。
*/
unsigned int avail;
/**
* 本地高速缓存的大小,也就是本地高速缓存中指针的最大个数
*/
unsigned int limit;
/**
* 本地高速缓存重新填充或者腾空时使用的块大小
*/
unsigned int batchcount;
/**
* 如果最近被使用过,则置为1
*/
unsigned int touched;
};
二、分配slab对象
1、函数先试图从本地缓存获得一个空闲对象;
2、如果本地缓存没有空闲对象就调用cache_alloc_refill(cachep, flags)函数;
//cachep 指向高速缓存描述符,新空闲对象必须从该告诉缓存描述符获得;
//flags是传递给物理页分配器的标志
static inline void * __cache_alloc (kmem_cache_t *cachep, int flags)
{
unsigned long save_flags;
void* objp;
struct array_cache *ac;
local_irq_save(save_flags);
/**
* 首先试图从本地高速缓存获得一个空闲对象。
*/
ac = ac_data(cachep);
/**
* 如果本地高速缓存有空闲对象,那么avail字段就包含