Linux内核设备驱动之内存管理笔记整理

2019-01-16 20:42:48王冬梅

a.分配

#include <linux/gfp.h> 1. struct page * alloc_pages( unsigned int gfp_mask, unsigned int order); //分配2的order次方个连续的物理页。 2. void *page_address( struct page *page); //返回一个指针,指向给定物理页当前的虚拟地址 3. unsigned long __get_free_pages( unsigned int gfp_mask, unsigned int order); //相当于上两个函数结合 4. struct page * alloc_page( unsigned int gfp_mask); 5. unsigned long __get_free_page( unsigned int gfp_mask); 6. unsigned long get_zeroed_page( unsigned int gfp_mask); //只分配一页

b.gfp_mask标志

这个标志决定了内核在分配内存时的行为,以及从哪里分配内存。

#include <linux/gfp.h> #define GFP_ATOMIC //原子分配,不会休眠,可用于中断处理。 #define GFP_KERNEL //首选,内核可能会睡眠,用在进程上下文中

c.释放页

void __free_pages(struct page *page, unsigned int order); void free_pages(unsigned long addr, unsigned int order); void free_page(unsigned long addr);

注意!只能释放属于你的页。错误的参数可能导致内核崩溃。

(3)通过kmalloc获取内存

kmalloc和malloc很象,是内核中最常用的内存分配函数。

kmalloc不会对分配的内存区域清0,分配的区域在物理内存中是连续的。

a.分配

#include <linux/slab.h> void *kmalloc(size_t size, int flags)

size是要求分配的内存的大小

kmalloc的参数flags可以控制kmalloc分配时的行为。和alloc_page时使用的标志是一致的。注意,kmalloc不能分配高端内存

b.释放

#include <linux/slab.h> void kfree(const void *ptr);

如果要释放的内存已经被释放了,或者释放属于内核其他部分的内存,则会产生严重的后果。调用kfree(NULL)是安全的。

要注意!内核只能分配一些预定义的,固定大小的字节数组。kmalloc能处理的最小内存块是32或64。由于kmalloc分配的内存在物理上连续,所以有分配上限,通常不要超过128KB。

(4)通过vmalloc获得内存

vmalloc()分配的内存虚拟地址是连续的,但物理地址不需要连续。这也是malloc()的分配方式。vmalloc分配非连续的内存块,再修改页表,把内存映射到逻辑空间连续的区域内。

大多数情况下,只有硬件设备需要得到物理地址连续的内存,内核可以使用通过vmalloc获得的内存。但内核中多采用kmalloc,这主要是考虑性能,因为vmalloc会引起较大的TLB抖动,除非映射大块内存时采用vmalloc。例如模块动态加载时,就是加载到通过vmalloc分配的内存。

vmalloc在<linux/vmalloc.h>声明,在<mm/vmalloc.c>定义,用法和malloc()相同。