——分配内存
仅为个人笔记,难免有错误~
一、Kmalloc函数的内幕
1.1 flags参数
kmalloc函数不对所获取的内存空间清零,分配给它的区域仍然保存原有的数据,这意味着要显式第清空内存,它分配的区域在屋里内存中也是连续的。其函数原型为:
#include
void *kmalloc(size_t size, gfp_t flags);
size -- 要分配的块的大小
flags -- 分配标志,这些标志在
GFP_KERNEL:Normal allocation of kernel memory. May sleep.
GFP_ATOMIC:Used to allocate memory from interrupt handlers and other code outside of a process context. Never sleeps.
Linux内核把内存分为三个区段:可用于DMA的内存、常规内存以及高端内存。
可用于DMA的内存指存在于特定地址范围的内存,外设可以利用这些内存执行DMA访问。
高端内存是32位平台为了访问大量的内存而存在的一种机制。
1.3 size参数
内核负责管理系统屋里内存,物理内存只能按页面进行分配。内核只能分配一些预定义的、固定大小的字节数组。kmalloc能处理的最小的内存块是32或者64。kmalloc能够分配的内存块大小,存在一个上限,不应该分配大于128KB的内存(保障代码具有可移植性)。
二、后备高速缓存
设备驱动程序常常会反复地分配很多同一大小的内存块,内核实现了这种形式的内存池,称为高速缓存(lookaside cache)。
创建一个新的高速缓存对象:
kmem_cache_t *kmem_cache_create(const char *name, size_t size,
size_t offset,
unsigned long flags,
void (*constructor)(void *, kmem_cache_t *,
unsigned long flags),
void (*destructor)(void *, kmem_cache_t *,
unsigned long flags));
创建高速缓存对象之后,可以调用:
void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags);
释放内存对象时使用:
void kmem_cache_free(kmem_cache_t *cache, const void *obj);
释放高速缓存对象,该操作只有在已经从缓存中分配的所有对象都归还后才能成功。
int kmem_cache_destroy(kmem_cache_t *cache);
三、内存池
四、get_free_page和相关函数
如果模块需要分配大块的内存,使用面向页的分配技术会更好。
get_zeroed_page(unsigned int flags);
Returns a pointer to a new page and fills the page with zeros.
__get_free_page(unsigned int flags);
Similar to get_zeroed_page, but doesn’t clear the page.
__get_free_pages(unsigned int flags, unsigned int order);
Allocates and returns a pointer to the first byte of a memory area that is potentially
several (physically contiguous) pages long but doesn’t zero the area.
当程序不再使用页面是,需要释放它们。
void free_page(unsigned long addr);
void free_pages(unsigned long addr, unsigned long order);
一个例子,来自国嵌
点击(此处)折叠或打开
-
#include <linux/module.h> //包含可装载模块需要的大量符合和函数的定义
-
#include <linux/init.h> //指定初始化和清除函数
-
-
char *buf1 = NULL;
-
char *buf2 = NULL;
-
-
int alloc_init()
-
{
-
buf1 = kmalloc(100,GFP_KERNEL);
-
memset(buf1,0,100);
-
strcpy(buf1,"<<< --- Kmalloc Mem OK! --- >>>");
-
printk("<0>BUF 1 : %s\n",buf1);
-
-
buf2 = get_zeroed_page(GFP_KERNEL);
-
strcpy(buf2,"<<<--- Get Free Page OK! --- >>>");
-
//printk("<0>BUF 2 : %s\n",buf2);
-
printk(KERN_EMERG "BUF 2: %s\n",buf2);
-
return 0;
-
}
-
-
void alloc_exit()
-
{
-
kfree(buf1);
-
free_page(buf2);
-
printk("<0><<< --- Module Exit! --->>>\n");
-
}
-
-
module_init(alloc_init);
-
module_exit(alloc_exit);
-
- MODULE_LICENSE("GPL")