Linux设备驱动程序 ——分配内存
仅为个人笔记,难免有错误~
一、Kmalloc函数的内幕 1.1 flags参数
kmalloc函数不对所获取的内存空间清零,分配给它的区域仍然保存原有的数据,这意味着要显式第清空内存,它分配的区域在屋里内存中也是连续的。其函数原型为: #include > void *kmalloc(size_t size, gfp_t flags);
size -- 要分配的块的大小
flags -- 分配标志,这些标志在中定义,常用的两个标志是GFP_KERNEL和GFP_ATOMIC 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. 1.2 内存区段
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);
一个例子,来自国嵌