发布网友 发布时间:2022-04-22 05:21
共1个回答
热心网友 时间:2023-11-28 11:28
处理器通过地址访问内存单元,程序中用到的基址加偏移地址是线性地址,需要通过MMU将虚拟地址映射成物理地址。这给分配和释放内存带来方便:1)物理地址不连续的空间可以映射为逻辑上连续的虚拟地址。2)进程可以获得比实际内存大的"空间",虚拟内存使得进程在这种情况下仍可正常运行。linux内核为驱动程序提供了一致的内存管理接口,因此不用考虑不同体系结构如何管理内存的。在linux内核中分配内存用kmalloc和kfree。kmalloc分配时可以被阻塞,且不对所获得的区域清零。它分配的区域在物理内存中也是连续的。原型:#includevoid*kmalloc(size_tsize,intflags);//参数为分配大小及分配标志flags参数:GFP_KERNEL:内核内存通用分配方法,表示内存分配是由运行在内核空间的进程执行的。可休眠,所以使用GFP_KERNEL分配内存的函数必须是可重入的。GFP_ATOMIC:用于在中断处理例程或者运行在进程上下文之外的代码中分配内存,不可休眠。内核通常会为原子性的分配预留一些空闲页面。所有标志定义在中。size参数:内核是基于页技术分配内存,以最佳的利用系统的RAM。linux处理内存分配的方法是:创建一系列的内存对象池,每个池的内存大小事固定的,处理分配请求时,就直接在包含足够大的内存块中传递一个整款给请求者。内核只能分配一些预定义的固定大小的字节数组。kmalloc能处理的的最小内存块是32或者,不大于128KB。内存区段:linux内核把内存分为3个区段:可用于DMA的内存,常规内存以及高端内存。kmalloc不能分配高端内存。内存区段在mm/page_alloc.c中实现。区段的初始化在对应的arch树下的mm/init.c中。后备高速缓存(lookasidecache)内核中普通对象进行初始化所需的时间超过了对其进行分配和释放所需的时间,因此不应该将内存释放回一个全局的内存池,而是将内存保持为针对特定目而初始化的状态。例如,如果内存被分配给了一个互斥锁,那么只需在为互斥锁首次分配内存时执行一次互斥锁初始化函数(mutex_init)即可。后续的内存分配不需要执行这个初始化函数,因为从上次释放和调用析构之后,它已经处于所需的状态中了。linux2.6中USB和SCSI驱动程序使用了这种高速缓存,是为一些反复使用的块增加某些特殊的内存池。后背高速缓存管理也叫slab分配器,相关函数和类型在中申明。slab分配器实现高速缓存具有kmem_cache_t类型。kmem_cache_t*kmem_cache_create(constchar*name,size_tsize,size_talign,unsignedlongflags;void(*constructor)(void*,kmem_cache_t*,unsignedlong),void(*destructor)(void*,kmem_cache_t*,unsignedlong));用于创建一个新的高速缓存对象。constructor用于初始化新分配的对象,destructor用于清除对象。一旦某个对象的高速缓存被创建以后,就可以调用kmem_cache_alloc从中分配内存对象。void*kmem_cache_alloc(kmem_cache_t*cache,intflags);释放内存对象使用kmem_cache_freevoidkmem_cache_free(kmem_cache_t*cache,constvoid*obj);在内存空间都被释放后,模块被卸载前,驱动程序应当释放他的高速缓存。intkmem_cache_destory(kmem_cache_t*cache);要检查其返回状态,如果失败,表明莫块中发生了内存泄露。基于slab的高速缓存scullckmem_cache_t*scullc_cache;scullc_cache=kmem_cache_creat("scullc",scullc_quantum,0,SLAB_HWCACHE_ALIGN,NULL,NULL);if(!scullc_cache){scullc_cleanup();return-ENOMEM;}if(!dpte->data[s_pos]){dptr->data[s_pos]=kmem_cache_alloc(scullc_cache,GFP_KERNEL);if(!dptr->data[s_pos])gotonomem;memset(dptr->data[s_pos],0,scullc_quantum);}for(i=0;idata[i])kmem_cache_free(scullc_cache,dptr->data[i]);}if(scullc_cache)kmem_cache_destory(scullc_cache);内存池:内核中有些地方的内存分配是不允许失败的,为确保能分配成功,内核建立一种称为内存池的抽象,他试图始终保持空闲状态,以便紧急情况使用。mempool_t*mempool_creat(intmin_nr,mempool_alloc_t*alloc_fn,//对象分分配mempool_alloc_slabmempool_free_t*free_fn,//释放mempool_free_slabvoid*pool_data);可以用如下代码来构造内存池cache=kmem_cache_creat();//创建一个高速缓存pool=mempool_creat(MY_POOL_MINIMUM,mempool_alloc_slab,mempool_free_slab,cache);//建立内存池对象void*mempool_alloc(mempool_t*poll,intgfp_mask);//分配对象void*mempool_free(void*element,mempool_t*poll);//释放对象voidmempool_destroy(mempool_t*poll);//销毁内存池注意:mempool会分配一些内存块,空闲且不会被用到,造成内存的大量浪费。所以一般情况不要用内存池。