linux内核中不连续页分配器

       

目录

不连续页分配器编程接口

 vmalloc执行过程


         当设备长时间运行,内存碎片化,很难找到连续的物理页。在这种情况下,如果需要分配长度超过一页的内存块,可以使用不连续页分配器,分配虚拟地址连续但是物理地址不连续的内存块。

        在32位系统中,不连续页分配器有一个好处:优先从高端内存区域分配,保留稀缺的低端内存区域。

        

不连续页分配器编程接口

  • vmalloc:分配不连续的物理页并且把物理页映射到连续的虚拟地址空间
  • vfree:释放vmalloc分配的物理页和虚拟地址空间
  • vmap:把已经分配的不连续物理页映射到连续的虚拟地址空间
  • vunmap:释放使用vmap分配的虚拟地址空间

  • kvmalloc函数:尝试先使用kmalloc分配内存块,如果失败,那么使用vmalloc函数分配不连续的物理页。
  • kfree函数 释放使用kvmalloc申请的内存。

        vmalloc虚拟地址空间的范围是[VMALLOC_START,VMALLOC_END)

ARM64架构下的VMALLOC_START,VMALLOC_END宏如下

/*
 * VMALLOC range.
 *
 * VMALLOC_START: beginning of the kernel vmalloc space
 * VMALLOC_END: extends to the available space below vmemmap, PCI I/O space
 *	and fixed mappings
 */

#define VMALLOC_START		(MODULES_END)
#define VMALLOC_END		(- PUD_SIZE - VMEMMAP_SIZE - SZ_64K)

其中

  • MODULES_END是内核模块区域的结束地址
  • PAGE_OFFSET是线性映射区域的起始地址
  • PUD_SIZE是一个页上层目录表项映射的地址空间长度
  • VMEMMAP_SIZE是vmemmap区域的长度

vmalloc虚拟地址空间的起始地址等于内核模块区域的结束地址;

vmalloc虚拟地址空间的结束地址等于(线性映射区域的起始地址-一个页上层目录表项映射的地址空间长度-vmemmap区域长度-64KB)

       


        vmalloc分配的是页,如果请求分配的长度不是页的整数倍,那么把长度对齐到页的整数倍。建议:在申请内存超过一页的时候吃药vmalloc。

        每个虚拟内存区域对应一个vmap_area实例,每个vmap_area实例关联一个vm_struct实例

linux内核中不连续页分配器_第1张图片

vmalloc执行过程

1)分配虚拟内存区域

        分配vm_struct实例和vmap_area实例,然后遍历已经存在的vmap_area实例,在两个相邻的虚拟地址内存区域之间找到一个足够大的空间,如果找到了,把起始虚拟地址和结束虚拟地址保存在vmap_area实例中,然后把vmap_area实例加入到红黑数和链表。最后把新的vmap_area实例关联到vm_struct实例。

2)分配物理页

        vm_struct实例的成员nr_pages存放页数n,分配page指针数组,数组大小是n,vm_struct实例的成员pages指向page指针数组;然后指向n次,从页分配器中分配一个物理页,把物理页对应的page实例的地址存放在page指针数组中。

3)在内核页表中把虚拟地址映射到物理地址页

        内核的页表就是0号线程的页表。0号内核线程的进程描述符是全局变量init_task,成员active_mm指针指向全局变量init_mm,init_mm成员pgd指向页全局目录swapper_pg_dir。

参考链接

https://course.0voice.com/v1/course/intro?courseId=2&agentId=0


 

你可能感兴趣的:(linux内核,不连续页分配,linux内核)