内存管理三之函数篇

来源:互联网 发布:笔记 软件 编辑:程序博客网 时间:2024/05/17 07:27

本文主要介绍内存申请的函数介绍:


1.vmalloc kmalloc  是用来分配内核空间内存的,malloc是用来分配用户空间的内存的。kmalloc分配的页在物理地址上是连续的(虚拟地址自然也是连续的),  vmalloc只确保

页在虚拟地址空间内是连续的。它通过非连续的物理内存块,再“修正”页表,把内存映射到逻辑地址空间是连续的区域内。 malloc返回的也在进程的虚拟地址空间内是连续

的,但是在物理地址上不一定是连续的

 

2. 用于kmalloc可分配的内存大小范围在32~131027(128k)字节,并且由于它用slab分配器来分配内存的,所以,得到的内存大小可能比你申请的要大一些(它向上取2的N次

幂整数)。而且如果开启了CONFIG_LARGE_ALLOCS选项,这个值可以更大,可以达到了32M。一般申请较大的内存才使用vmalloc,例如当模块被动态加载到内核当中时,

就把模块装载到由vmalloc()分配 的内存上。

 

3.vmalloc是会睡眠的,因此不能在中断上下文中使用。 kmalloc可以通过配置flags配置为可睡眠或者不可睡眠,GFP_KERNEL可以睡眠 GFP_ATOMIC不可以睡眠。

 

4.内核中vmalloc,kmalloc分配都是以字节为单位,若想以页为单位用alloc_pages类函数 当然,内核进行内存管理(MMU干的)是以物理页为基本单位的。

 

 

简单的说:

  1. kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存
  2. kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(猜测的,不一定正确)
  1. kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大
  1. 内存只有在要被DMA访问的时候才需要物理上连续
  1. vmalloc比kmalloc要慢
  1. kmalloc()是内核中最常见的内存分配方式,它最终调用伙伴系统__get_free_pages()函数分配,根据传递给这个函数的flags参数,决定这个函数的分配适合什么场合,如果标志是GFP_KERNEL则仅仅可以用于进程上下文中,如果标志GFP_ATOMIC则可以用于中断上下文或者持有锁的代码段中。
    kmalloc返回的线形地址是直接映射的,而且用连续物理页满足分配请求,且内置了最大请求数(2**5=32页)。
  1. vmalloc优先使用高端物理内存,但性能上会打些折扣。
    vmalloc分配的物理页不会被交换出去; 
    vmalloc返回的虚地址大于(PAGE_OFFSET + SIZEOF(phys memory) + GAP),为VMALLOC_START----VMALLOC_END之间的线形地址; 
    vmalloc使用的是vmlist链表,与管理用户进程的vm_area_struct要区别,而后者会swapped;
  1. kmap()是主要用在高端存储器页框的内核映射中,一般是这么使用的:
    使用alloc_pages()在高端存储器区得到struct page结构,然后调用kmap(struct *page)在内核地址空间PAGE_OFFSET+896M之后的地址空间中(PKMAP_BASE到FIXADDR_STAR)建立永久映射(如果page结构对应的是低端物理内存的页,该函数仅仅返回该页对应的虚拟地址)
    kmap()也可能引起睡眠,所以不能用在中断和持有锁的代码中
    不过kmap 只能对一个物理页进行分配,所以尽量少用。
    对于高端物理内存(896M之后),并没有和内核地址空间建立一一对应的关系(即虚拟地址=物理地址+PAGE_OFFSET这样的关系),所以不能使用get_free_pages()这样的页分配器进行内存的分配,而必须使用alloc_pages()这样的伙伴系统算法的接口得到struct *page结构,然后将其映射到内核地址空间,注意这个时候映射后的地址并非和物理地址相差PAGE_OFFSET.

kmallocget_free_page申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因此存在较简单的转换关系。而vmalloc申请的内存则位于vmalloc_start~vmalloc_end之间,与物理地址没有简单的转换关系,虽然在逻辑上它们也是连续的,但是在物理上它们不要求连续。

 

 

kmalloc()和vmalloc()介绍

kmalloc()

用于申请较小的、连续的物理内存

1. 以字节为单位进行分配,在<linux/slab.h>中

2. void *kmalloc(size_t size, int flags)分配的内存物理地址上连续,虚拟地址上自然连续

3. gfp_mask标志:什么时候使用哪种标志?如下:

———————————————————————————————-

情形                          相应标志

———————————————————————————————-

进程上下文,可以睡眠          GFP_KERNEL

进程上下文,不可以睡眠        GFP_ATOMIC

中断处理程序                  GFP_ATOMIC

软中断                        GFP_ATOMIC

Tasklet                       GFP_ATOMIC

用于DMA的内存,可以睡眠       GFP_DMA| GFP_KERNEL

用于DMA的内存,不可以睡眠     GFP_DMA| GFP_ATOMIC

———————————————————————————————-

4. void kfree(const void *ptr)

释放由kmalloc()分配出来的内存块

 

vmalloc()

用于申请较大的内存空间,虚拟内存是连续的

1. 以字节为单位进行分配,在<linux/vmalloc.h>中

2. void *vmalloc(unsigned long size)分配的内存虚拟地址上连续,物理地址不连续

3.一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用kmalloc(),而只有在需要获得大块内存时才使用vmalloc(),例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配 的内存上。

4.void vfree(void *addr),这个函数可以睡眠,因此不能从中断上下文调用。

malloc(), vmalloc()和kmalloc()区别

[*]kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存

[*]kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(这点是自己猜测的,不一定正确)

[*]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大

[*]内存只有在要被DMA访问的时候才需要物理上连续

[*]vmalloc比kmalloc要慢

0 0