虽然Linux的内存管理相当复杂,但是使用起来还是比较简单的。
Linux内存分配器(__get_free_pages alloc_pages),基于伙伴系统,其中alloc_pages可以在分配高端内存。而__get_free_pages只能分配低端内存。并且他们分配的内存在物理上都是连续的。使用alloc_pages分配的高端内存需要通过kmap建立映射以获得内核虚拟地址进行访问,而分配的低端内存,因为映射在系统初始化的时候就已经建立,所以可以直接使用page_address宏获得线性地址进行访问。
至于slab分配器,使用alloc_pages在低端内存分配的空间。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/percpu.h>
static int __init hello_init (void)
{
struct page * page; // 页描述符
void * ptr;
struct kmem_cache * kmem_cache;
/* 1.直接使用页面分配器 */
/* 1.1 分配低端内存*/
page = alloc_pages(GFP_KERNEL | GFP_ATOMIC, 1);
ptr = page_address(page);
__free_pages(page, 1);
ptr = __get_free_pages(GFP_KERNEL, 1);
free_page(ptr);
/* 1.2 分配高端内存 */
/* 高端内存本身没有映射到内核虚拟空间,
* 通过页面分配器分配后必须通过kmap将页面描述符
* 对应的高端内存映射至内核空间方可使用*/
page = alloc_pages(__GFP_HIGHMEM, 1);
ptr = kmap(page);
kunmap(page);
__free_pages(page, 1);
/* 2.使用slab分配器分配内存空间 */
kmem_cache = kmem_cache_create ("my_slab", 12, 0,0, NULL);
ptr = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
kmem_cache_free(kmem_cache, ptr);
kmem_cache_destroy(kmem_cache);
/* 3.使用vmalloc在动态影射区分配内存(物理内存可能不连续,分配大块内存)*/
ptr = vmalloc(1024);
vfree(ptr);
return 0;
}
static void __exit hello_exit (void)
{
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Tian bei");
MODULE_DESCRIPTION("per_cpu_ptr test");
MODULE_LICENSE("GPL");