页和区
内核把物理页作为内存管理的基本单位。MMU(管理内存并把虚拟地址转换为物理地址的硬件)以页(page)的大小为单位来管理系统中的页表。大多数32位体系结构支持4KB的页,而64位一般会支持8KB的页。
struct page表示系统中的每个物理页<linux/mm.h>
struct page {
page_flags_t flags; //存放页的状态,定义在<linux/page-flag.h>
atomic_t _count; //页被引用的次数
atomic_t _mapcount;
unsigned long private;
struct address_space *mapping;
pgoff_t index;
struct list_head lru;
void *virtual;
}
内核仅仅用这个数据结构来描述当前时刻在相关的物理页存放的东西。该结构目的在于描述物理内存本身,不描述包含其中的数据。内核把页划分为不同的区(zone)定义位于<linux/mmzone.h>中:
ZONE_DMA (<16M)包含的页能用来执行DMA操作;
ZONE_NORMAL (16~892M)包含的都是能正常映射的页;
ZONE_HIGHMEM (>892M)包含“高端内存”其中的页并不能永久地映射到内核地址空间
如何获得和释放页?
alloc_page(gfp_mask) 只分配一页,返回指向页结构的指针
alloc_page(gfp_mask,order) 分配2的order次方个页,返回第一页结构指针
_get_free_page(gfp_mask) 只分配一页,返回指向其逻辑地址的指针
__get_free_pages(gfp_mask,order) 分配2的order次方页,返回第一页逻辑地址的指针
get_zeroed_page(gfp_mask) 只分配一页,内容填充0,返回指向其逻辑地址的指针
void __free_pages(struct page * page,unsigned int order)
void free_pages(unsigned long addr,unsigned int order)
void free_page(unsigned long addr)
关于kmalloc()和kfree()
kmalloc函数声明在<linux/slab.h>中,void *kmalloc(size_t size,int flags)该函数和用户空间的malloc函数非常类似。函数返回一个指向内存块的指针,其内存块大小至少要有size大小。所分配的内存在物理上是连续的。kfree用于释放上函数分配的内存,不可释放其他的内存,调用函数kfree(NULL)是安全的。
关于gfp_mask标志
分为三类<linux/gfp.h>:行为修饰符,表示内核应如何分配所需内存;区修饰符,表示从哪开始分配内存;类型,组合前两种,归纳为不同类型。进程上下文,可以睡眠时使用GFP_KERNEL;进程上下文,不可以睡眠时使用GFP_ATOMIC,在你睡眠之前或者之后用GFP_KERNEL执行内存分配;中断处理程序,软中断,tasklet是使用GFP_ATOMIC。
关于vmalloc
在<linux/vmalloc.h>声明,定义在<mm/vmalloc.c>,函数确保页在虚拟地址空间内是连续的,而在物理内存并非连续。由于必须建立专门的页表项,产生比直接内存映射大得多的TLB抖动,性能不如kmalloc,内核大多数情况使用kmalloc获得内存。vmalloc在不得已才使用,如模块动态插入到内核是,模块装载到vmalloc分配的内存上。用法和malloc相同,函数可能睡眠,不能从中断上下文中进行调用,也不能从其他不允许阻塞的情况下进行调用。
slab层
slab分配器扮演了通用数据结构缓存层的角色。slab层把不同的对象分为高速缓存组,其中每个高速缓存存放着不同的类型的对象。每个slab都包含一些对象成员,这里的对象指的是被缓存的数据结构,每个slab处于三种状态之一:满,部分满或空。
内核把物理页作为内存管理的基本单位。MMU(管理内存并把虚拟地址转换为物理地址的硬件)以页(page)的大小为单位来管理系统中的页表。大多数32位体系结构支持4KB的页,而64位一般会支持8KB的页。
struct page表示系统中的每个物理页<linux/mm.h>
struct page {
page_flags_t flags; //存放页的状态,定义在<linux/page-flag.h>
atomic_t _count; //页被引用的次数
atomic_t _mapcount;
unsigned long private;
struct address_space *mapping;
pgoff_t index;
struct list_head lru;
void *virtual;
}
内核仅仅用这个数据结构来描述当前时刻在相关的物理页存放的东西。该结构目的在于描述物理内存本身,不描述包含其中的数据。内核把页划分为不同的区(zone)定义位于<linux/mmzone.h>中:
ZONE_DMA (<16M)包含的页能用来执行DMA操作;
ZONE_NORMAL (16~892M)包含的都是能正常映射的页;
ZONE_HIGHMEM (>892M)包含“高端内存”其中的页并不能永久地映射到内核地址空间
如何获得和释放页?
alloc_page(gfp_mask) 只分配一页,返回指向页结构的指针
alloc_page(gfp_mask,order) 分配2的order次方个页,返回第一页结构指针
_get_free_page(gfp_mask) 只分配一页,返回指向其逻辑地址的指针
__get_free_pages(gfp_mask,order) 分配2的order次方页,返回第一页逻辑地址的指针
get_zeroed_page(gfp_mask) 只分配一页,内容填充0,返回指向其逻辑地址的指针
void __free_pages(struct page * page,unsigned int order)
void free_pages(unsigned long addr,unsigned int order)
void free_page(unsigned long addr)
关于kmalloc()和kfree()
kmalloc函数声明在<linux/slab.h>中,void *kmalloc(size_t size,int flags)该函数和用户空间的malloc函数非常类似。函数返回一个指向内存块的指针,其内存块大小至少要有size大小。所分配的内存在物理上是连续的。kfree用于释放上函数分配的内存,不可释放其他的内存,调用函数kfree(NULL)是安全的。
关于gfp_mask标志
分为三类<linux/gfp.h>:行为修饰符,表示内核应如何分配所需内存;区修饰符,表示从哪开始分配内存;类型,组合前两种,归纳为不同类型。进程上下文,可以睡眠时使用GFP_KERNEL;进程上下文,不可以睡眠时使用GFP_ATOMIC,在你睡眠之前或者之后用GFP_KERNEL执行内存分配;中断处理程序,软中断,tasklet是使用GFP_ATOMIC。
关于vmalloc
在<linux/vmalloc.h>声明,定义在<mm/vmalloc.c>,函数确保页在虚拟地址空间内是连续的,而在物理内存并非连续。由于必须建立专门的页表项,产生比直接内存映射大得多的TLB抖动,性能不如kmalloc,内核大多数情况使用kmalloc获得内存。vmalloc在不得已才使用,如模块动态插入到内核是,模块装载到vmalloc分配的内存上。用法和malloc相同,函数可能睡眠,不能从中断上下文中进行调用,也不能从其他不允许阻塞的情况下进行调用。
slab层
slab分配器扮演了通用数据结构缓存层的角色。slab层把不同的对象分为高速缓存组,其中每个高速缓存存放着不同的类型的对象。每个slab都包含一些对象成员,这里的对象指的是被缓存的数据结构,每个slab处于三种状态之一:满,部分满或空。