现
代计算机!总第二三五期"
MODERNCOMPUTER2006.5
实践与经验
1Linux内存管理体系
在Intel80x86体系结构中,Linux内核的内存管
理采用了分页管理方式,真正实现了虚拟存储器管理,其虚拟内存管理的实现结构如图1所示。
图1
内存映射模块负责把磁盘文件的逻辑地址映射到虚拟地址,把虚拟地址映射到物理地址;交换模块负责控制内存内容的换入和换出;核心管理模块负责核心内存管理功能,即对页的分配、
回收、释放及请页处理等;结构特定的模块负责给各种硬件提供通用接口,这个模块通过执行命令来改变硬件MMU的虚拟地址映射。
Linux虚拟内存的实现机制为:内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址,在用户程序运行时如果发现程序中要用到的虚地址没有对应的物理内存时,就发出了请页要求;如果有空闲的内存可供分配,就请求分配内存,并把正在使
用的物理页纪录在页缓存中。如果没有足够的内存可供分配,那么就调用交换机制,腾出一部分内存。另外,在地址映射中要通过TLB来寻物理页,交换机制中也要用到交换缓存,并且把物理页内容交换到交换文件后也要修改页表来映射文件地址。
2Slab分配机制概述
Slab分配机制用来对内存区域中内核空间进行
分配和回收。Slab使用对象来组织内存区域,对象就是指存放一组数据结构的内存区。Slab根据内存区的使用频率对内存区域进行划分。对于预期频繁使用的内存区,Slab创建一组特定大小的专用缓冲区进行处理,以避免内碎片的产生;对于较少使用的内存区,
Slab创建一组通用缓冲区来处理,即使这种处理模式产生碎片,对整个系统的性能影响也不大。
Slab分配模式把对象分组放进缓冲区,Slab缓冲区并非由各个对象直接构成,而是由一连串的Slab构成,而每个大块中则包括了若干个同种类型的对象。
高速缓存、Slab及对象之间的关系如图2所示。
图2
Linux内存管理中的Slab分配机制
赵鲲鹏1
,
苏葆光2
(1.长安大学,西安710061;2.浙江万里学院,宁波315101)
摘
要:早期Linux的内存分配机制采用伙伴算法,当请求分配的内存大小为几十个字节或几百个
字节时会产生内存碎片,严重消耗系统资源。现今采用Slab机制可以缓存物理空间的申请和回收,杜绝外部碎片的产生,降低内部碎片量。本文分析了Slab内存分配机制及其数据结构和接口函数,然后给出了Slab机制的实现。
关键词:Slab;内存管理;Linux;分配机制
!
"
实践与经验
现代计算机!总第二三五期"
3Slab数据结构和接口
(1)Slab数据结构
Slab是Slab管理模式中最基本的结构。它是由
一组连续的物理页面组成,对象就被顺序放在这些页
面中。其数据结构定义如下:
typedefstructslab_s{
structlist_headlist;
unsignedlongcolouroff;
void*s_men;
unsignedintinuse;
kmen_bufct1_tfree;
}slab_t;
list用来将前一个和后一个Slab链接起来形成一
个双向链表;colouroff为该Slab上着区大小,着
区的大小使Slab中的每个对象的起始地址都按高速
缓存中的“缓存行”大小进行对齐;指针s_men指向对
象区的起点;inuse是Slab中所分配对象的个数;free
的值指明了空闲对象链中的第一个对象。对于小对
象,就把Slab的描述结构slab_t放在该Slab中;对于
大对象,则把Slab结构游离出来,集中存放。
(2)缓冲区数据结构
每个缓冲区管理着一个Slab链表,Slab按序分
为3组。第1组是全满的Slab;第2组Slab中只有部
分对象被分配;第3组Slab中的对象全部空闲。每个
缓冲区还有一个轮转锁(Spinlock),在对链表进行修
改时用这个轮转锁进行同步。缓冲区类型
kmem_cache_s定义及注释如下:
structkmem_cache_s{
structlist_headslabs_full;//全满Slab链表
structlist_headslabs_partial;
//部分对象被分配的Slab链表
structlist_headslabs_free;//空闲Slab链表
unsignedintobjsize;//对象的大小
unsignedintflags;//属性标志
unsignedintnum;//slab中对象的数目
spinlock_tspinlock;//自旋锁
#indefCONFIG_SMP//如果是对称多处理器
unsignedintbatchcount;//定义一个批处理计数
#endif
//以下是关于Slab的增加和消除的
unsignedintgfporder;//Slab中页面数目
unsignedintgfpflags;//申请页面的优先级
size_tcolour;//着的范围
unsignedintcolour_off;//着的偏移量
unsignedintcolour_next;//下一个着的
kmem_cache_t*slabp_cache;
//指向cache_slabp缓冲区的指针
unsignedintgrowing;
//对正在增长的Slab设置的标志
unsignedintdflags;
//对动态作的标志
void(*ctor)(void*,kmem_cache_t*,unsigned
long);//构造函数
void(*dtor)(void*,kmem_cache_t*,unsigned
long);//析构函数
unsignedlongfailures;//失败标记
//以下是关于缓存的增加和消除的
charname[CACHE_NAMELEN];//缓存区的名字
structlist_headnext;//指向下一个缓存结构的指针
#indefCONFIG_SMP//对称多处理器的编译预处理
cpucache_t*cpudata[NR_CPUS];
//设置指向每一个CPU运行的指针
#endif
#ifSTATS//编译预处理,如果需要记录状态
unsignedlongnum_active;//活跃的数目
unsignedlongnum_allocations;//分配的数目
unsignedlonghigh_mark;//最多活跃的标记
unsignedlonggrown;//增长标记
unsignedlongreaped;//回收的标记
unsignedlongerrors;//出错的标记
#ifdefCONFIG_SMP编译预处理,如果定义了对称多处
理器
atomic_tallochit;//原子计数器分配命中数
atomic_tallocmiss;//原子计数器分配未命中数
atomic_tfreehit;//原子计数器释放命中数
atomic_tfreemiss;//原子计数器释放未命中数
#endif
#endif
};
缓冲区结构头指针kmem_cache_t定义及注释如下:
statickmem_cache_tcache_chche={
slabs_full;LIST_HEAD_INIT(cache_cache,slabs_
full),//全满Slab链表
slabs_partial;LIST_HEAD_INIT(cache_cache,slabs_
partial),//部分对象被分配的Slab链表
slabs_free;LIST_HEAD_INIT(cache_cache,slabs_
free),//空闲Slab链表
objsize;sizeof(kmem_cache_t),//对象的大小
flags;SLAB_NO_REAP,//属性标志
spinlockSPIN_LOCK_UNLOCKED,//自旋锁
colour_off;L1_CACHE_BYTES,//设定着范围
为1级缓存的大小
name;"kmem_cache",//设置名称
};
(3)缓存接口
创建某类对象的缓存函数为:
!"
MODERNCOMPUTER2006.5
现
代计算机!总第二三五期"
MODERNCOMPUTER2006.5
实践与经验
SlabAssigningMechanisminMemoryManagementofLinux
ZHAOKun-peng1,
SUBao-guang2
(1.Chang'anUniversity,Xi'an710061China;2.ZhejiangWanliUniversity,Ningbo315101China)
Abstract:ThispaperintroducesSlabAssigningmechanisminmemorymanagementinLinuxandconstructionof
dataandcodesinit.ThispaperalsointroduceshowtouseSlabAssigningmachineandgivesanexample.
Keywords:Slab;MemoryManagement;Linux;AssigningMechanism
Kmem_cache_t*kmem_cache_create(constchar*name,size_tsize,size_toffset,unsignedlongc_flags,void(*ctor)(void*objp,kmem_cache*cachep,unsignedlongflags),void(*dtor)(void*objp,kmem_cache_t*cachep,unsignedlongflags))
从缓存中获得一个对象的函数为:
linux内核设计与实现 pdfstaticinlinevoid*_kmem_cache_alloc(kmem_cache_t*cachep,intflags)
释放对象到缓存的函数为:
staticinlinevoid_kmem_cache_free(kmem_cache_
t*cachep,constvoid*objp)
当缓存为空或者没有多余的空闲对象满足申请时,向页面级分配器索要物理空间,并创建和初始化对象:
staticintkmem_cache_grow(kmem_cache_t*cachep,intflags)
当页面级分配器需要内存时,搜索所有缓存,析构缓存中的空闲对象,最后回收这些对象占用内存的函数为:
voidkmem_cache_reap(intgfp_mask)
缓存销毁函数为:
intkmem_cache_destroy(task_struct_cachep)
4Slab的使用
使用过程:
分配一个对象;
if(该缓存中有空闲的对象)
直接使用对象;
else{
为该缓存分配空间;构造新的对象;
}
使用后释放一个对象;
使用实例:
kmem_cache_t*task_struct_cachep;
task_struct_cachep=kmem_cache_create("task_struct",sizeof(structtask_struct),0,SLAB_MUST_HWCACHE_ALIGN,NULL,NULL);
if(!task_struct_cachep)
panic("fork_init();cannotcreatetask_structSLAB
cache");
structtask_struct*tsk;
tsk=kmem_cache_alloc(task_struct_cachep,GFP_KER-NEL);
if(!tsk){
free_thread_info(ti);returnNULL;}
使用task_struct_cachep;
kmem_cache_free(task_struct_cachep,tsk);
结语
Slab分配器的概念首先在SUNMicrosystem的SUNOS5.4操作系统中实现。早期版本的Linux的内核区域分配算法采用伙伴算法,每次至少分配一个页面。当请求分配的内存大小为几十个字节或几百个字节时会产生内碎片,造成浪费。现今采用Slab机制可以方便缓存物理空间的申请和回收,杜绝外部碎片的产生,使内部碎片量降低到最小。
参考文献
[1]MichaelBeck等.Linux内核编程指南.张瑜等译.北京:清华大学出版社,2004
[2]陈莉君.深入分析Linux内核源代码.北京:人民邮电出版社,2002
[3]RobertLove等.Linux内核设计与实现.陈莉君等译.北京:机械工业出版社,2005
[4]洪津津,石教英.Linux中的Slab分配器.计算机应用研究,2000(29)
(收稿日期:2006-03-10)
!
"
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论