// cache 的构造或移除 constchar *name; // cache 的名字 structlist_headlist; int refcount; int object_size; int align;
// debug 和统计信息不关注
// 每 cpu 每 内存节点的数据 /* * We put array[] at the end of kmem_cache, because we want to size * this array to nr_cpu_ids slots instead of NR_CPUS * (see kmem_cache_init()) * We still use [NR_CPUS] and not [1] or [0] because cache_cache * is statically defined, so we reserve the max number of cpus. * * We also need to guarantee that the list is able to accomodate a * pointer for each node since "nodelists" uses the remainder of * available pointers. */ structkmem_cache_node **node;// ULK3 里面的 kmem_list3 结构体 structarray_cache *array[NR_CPUS + MAX_NUMNODES];// 数组指针,每一项对应 cpu 或 numa 节点 };
不同于 Solaris 2.4 实现,Linux 自引入 slab 就是要考虑多处理器情况,而 array_cache 结构体的目的正是优化多处理下一些性能问题,更好的利用 cpu 的高速缓存。在分配和释放对象时候,以 LIFO 序从 _alloc 分发缓存过热的对象。减少链表的操作。减少自旋锁的操作。
每一个 array_cache 结构体描述一个本地 cache 的中 free 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
structarray_cache { unsignedint avail; // available 指向当前可用对象指针的数量 unsignedint limit; // 缓存在收缩之后空闲对象数量上限 unsignedint batchcount; // 在 per-CPU 列表为空的情况下,从 cache 的 slab 中获取对象的数目 unsignedint touched; // 从 cache 移除时 touched 为 1,cache 收缩时则 0. spinlock_t lock; void *entry[]; /* 下面注释写的蛮清楚的 * Must have this definition in here for the proper * alignment of array_cache. Also simplifies accessing * the entries. * * Entries should not be directly dereferenced as * entries belonging to slabs marked pfmemalloc will * have the lower bits set SLAB_OBJ_PFMEMALLOC */ };