Chinaunix首页 | 论坛 | 博客
  • 博客访问: 476826
  • 博文数量: 144
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 508
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-10 13:18
个人简介

Keep looking Donot settle

文章分类

全部博文(144)

文章存档

2019年(1)

2016年(31)

2015年(51)

2014年(61)

分类: 嵌入式

2014-10-10 19:43:36

1. 页

内核把物理页作为内存管理的最小单位,尽管处理器的最小寻址单位通常为字,但是,内存管理单元(MMU)通常以页为单位进行处理。必须理解一点page结构与物理页相关,而非与虚拟页相关,物理页中存放的数据由于交换等原因,可能被交换出去,它们可能并不再和同一个page结构相关联,内核仅仅用这个数据结构来描述当前时刻物理页中存放的东西。这种数据结构的目的在于描述物理内存本身,而不是描述其中的数据。一般情况下32位体系结构,页的大小为4KB。而64位体系结构一般会支持8KB的页。

 

2.区

由于硬件的限制,内核并不能一视同仁的对待所有的页,有些页位于内存中特定的物理地址上,所以不能将其用于一些特定的任务,由于存在这种限制,所以内核把页划分为不同的区。

Linux内核使用了三种区:

ZONE_DMA  -这个区包含的页用来执行DMA操作

ZONE_NORMAL-这个区包含的都是正常映射的页

ZONE_HIGHMEM-这个区包含"高端内存",其中的页并不能永久的映射到内核地址空间

在X86上:

ZONE_DMA        <16MB

ZONE_NORMAL  16-896MB

ZONE_HIGHMEM >896MB

 

 

3.获得页与释放页

内核提供一种请求内存的底层机制,并提供了对它访问的几个接口,所有的这些接口都是以页为单位分配内存,定义于中。

struct page* alloc_pages(unsigned int gfp_mask,unsigned int order);

该函数分配2的order次幂连续的物理页,并返回一个指针,该指针指向第一个页的page结构体。如果出错,则返回空。

 

void *page_address(struct page* page);

该函数返回一个指针,指向当前物理页所在的逻辑地址。传递的参数是page结构体指针

这个地址是内核虚拟地址,即内核可以直接访问的地址。

 

unsigned long _ _get_free_pages(unsigned int gfp_mask,unsigned int order)

这个函数返回的所请求的页的内核空间的虚拟地址。

 

 

struct page* alloc_page(unsigned int gfp_mask)

unsigned long __get_free_page(unsigned int gfp_mask);

返回的是单页。

 

 

unsigned long get_zeroed_page(unsigned int gfp_mask);

这个函数与__get_free_page工作方式相同,只不过把分配好的页都填为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);

 

4. kmalloc与vmalloc函数

kmalloc:

kmalloc函数与用户空间的malloc一族函数非常类似,只不过它多了一个flags参数。

kmalloc函数是一个简单的接口,用以获得以字节为单位的一块内核内存。如果你需要整个页,那么,前面讨论的页可能是最好的选择。

kmalloc函数在

void *kmalloc(size_t size,int flags);

void kfree(const void* addr);

这个函数返回的是指向内存的内核逻辑地址的指针,其内存块大小至少为size大小。所分配的内存区在物理上是连续的。

 

 

 

vmalloc:

vmalloc函数类似于kmalloc,只不过前者分配的内存虚拟地址是连续的,而物理地址无需连续。kmalloc函数保证的页的物理地址是连续的,内核虚拟地址也是连续的,而vmalloc只保证页在虚拟地址空间是连续的,它通过分配非连续的物理内存块,再“修正”页表,把内存映射到逻辑地址空间的连续区域中,就能做到这点。

 

因此,vmalloc函数为了把物理上不连续的页转换成虚拟地址空间上连续的页,必须建立页表项。vmalloc获得的页必须一个一个的进行映射,因为它们在物理上是不连续的。这直接导致比直接内存映射大得多的TLB抖动。

 

void *vmalloc(unsigned long size);

void vfree(void *addr);

 

 

 

kmalloc与vmalloc返回的都是内核虚拟地址(内核可以访问的地址),这些地址对应着物理内存中的一个个页面,kmalloc得到的地址也称为“逻辑地址”,因为是连续的页,访问物理内存只需要一个偏移量计算即可。

 

关于Linux内存管理就介绍到这了。

阅读(644) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~