日期:2014-05-16  浏览次数:20535 次

Linux内核之内核缓冲区的管理

Linux内核采用slab方法来管理内核缓冲区,slab类似于面向对象的方法进行内核区的分配和回收。

?

1. slab可能由1个,2个,4个.......最多32个连续的物理页面构成;

2. 每个slab都有slab的描述结构slab_t,用于同一种对象或多个slab通过描述结构队列头形成一个双向链队列。每个slab结构逻辑上分成3段,对一段是各个slab上所有的对象都已分配使用;第二个是各个slab已经部分使用;最后一段是各个slab上的全部对象都处于空闲状态。

3. 每个slab上都有一个对象区,这是对象数据结构的数组,以对象的序号为下标就可以得到具体对象的起始地址;

4. 每个slab上还有一个对象链接数组,用来实现一个空闲对象链;

5. 每个slab上有个字段,表明slab上第一个空闲的对象;

6. slab上还有一个计数器,当一个空闲对象分配时,计数器加1,并从空闲队列中脱链;

7. 当释放一个对象时,只要调整链接数组中的相应元素以及计数器,并且根据此slab的使用情况调整其在slab中的位置;

8. slab的头部都有一个着色区,用来和高速缓存对齐,并且每个slab的着色区尽量安排成不同大小,以使得不同slab上的同一位置的对象的起始地址在高速缓冲中相互错开;

9. 每个slab上最后一个对象也有一个小小的废料区是不用的,这是对着色区的补偿。但该区域与着色区的总和对于同一种对象的各个slab是个常数;

?

系统有个总的slab队列,其对象是各个其它对象的slab队头,其对象是各个其他对象的slab队头。对于大对象和小对象,slab结构略有不同。小对象的控制结构不是放在它所在的slab上,而是集中放置在另外的slab上。并非所有内核的数据结构都使用专用的缓冲区队列,一些不太常用的或初始化开销不大的还是使用通用的缓冲机制。

?

所以Linux中还有既类似于物理页面中所采用按大小分配的方法,又采用slab方式管理的通用缓冲池,称为slab_cache与cache_cache不同,它的顶层不是一个队列而是一个结构数组,数组中的每个元素指向一个不同的slab队列。这些slab队列的不同之处在于所载对象的大小,最小32,64直至128K。

?

分配一个不具slab队列的数据结构而不必为之使用整个页面时,就应该通过kmalloc()分配,释放是kfree();大小接近一个页面时,使用alloc_pages()。

vmalloc()从内核虚拟空间(3G以上)分配一块虚存以及物理内存,类似于系统调用brk();只不过brk()是由进程在用户空间启动并从用户空间分配,而vmalloc()则是在系统空间启动并分配的。由vmalloc()分配的空间不会被kswapd换出,因为kswapd只扫描各进程的用户空间;对于kmalloc()分配的空间,kswapd只是在各个slab队列中寻找和收集空闲不用的slab,不会将尚在使用的slab所占的页面换出