背景

  • Read the fucking source code! --By 鲁迅
  • A picture is worth a thousand words. --By 高尔基

说明:

  1. Kernel版本:4.14
  2. ARM64处理器,Contex-A53,双核
  3. 使用工具:Source Insight 3.5, Visio

1. 概述

在之前的系列文章中,分析到了Buddy System的页框分配,Slub分配器的小块内存对象分配,这些分配的地址都是物理内存连续的。当内存碎片后,连续物理内存的分配就会变得困难,可以使用vmap机制,将不连续的物理内存页框映射到连续的虚拟地址空间中。vmalloc的分配就是基于这个机制来实现的。

还记得下边这张图吗?

vmap/vmalloc的区域就是在VMALLOC_START ~ VMALLOC_END之间。

开启探索之旅吧。

2. 数据结构

2.1 vmap_area/vm_struct

这两个数据结构比较简单,直接上代码:

struct vm_struct {struct vm_struct   *next;void          *addr;unsigned long     size;unsigned long      flags;struct page       **pages;unsigned int        nr_pages;phys_addr_t        phys_addr;const void        *caller;
};struct vmap_area {unsigned long va_start;unsigned long va_end;unsigned long flags;struct rb_node rb_node;         /* address sorted rbtree */struct list_head list;          /* address sorted list */struct llist_node purge_list;    /* "lazy purge" list */struct vm_struct *vm;struct rcu_head rcu_head;
};

struct vmap_area用于描述一段虚拟地址的区域,从结构体中va_start/va_end也能看出来。同时该结构体会通过rb_node挂在红黑树上,通过list挂在链表上。
struct vmap_areavm字段是struct vm_struct结构,用于管理虚拟地址和物理页之间的映射关系,可以将struct vm_struct构成一个链表,维护多段映射。

关系如下图:

2.2 红黑树

红黑树,本质上是一种二叉查找树,它在二叉查找树的基础上增加了着色相关的性质,提升了红黑树在查找,插入,删除时的效率。在红黑树中,节点已经进行排序,对于每个节点,左侧的的元素都在节点之前,右侧的元素都在节点之后。
红黑树必须满足以下四条规则:

  1. 每个节点不是红就是黑;
  2. 红黑树的根必须是黑;
  3. 红节点的子节点必须为黑;
  4. 从节点到子节点的每个路径都包含相同数量的黑节点,统计黑节点个数时,空指针也算黑节点;

定义如下:

struct rb_node {unsigned long  __rb_parent_color;struct rb_node *rb_right;struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));/* The alignment might seem pointless, but allegedly CRIS needs it */

由于内核会频繁的进行vmap_area的查找,红黑树的引入就是为了解决当查找数量非常多时效率低下的问题,在红黑树中,搜索元素,插入,删除等操作,都会变得非常高效。至于红黑树的算法操作,本文就不再深入分析,知道它的用途即可。

3. vmap/vunmap分析

3.1 vmap

vmap函数,完成的工作是,在vmalloc虚拟地址空间中找到一个空闲区域,然后将page页面数组对应的物理内存映射到该区域,最终返回映射的虚拟起始地址。

整体流程如下:

操作流程比较简单,来一个样例分析,就清晰明了了:

vmap调用中,关键函数为alloc_vmap_area,它先通过vmap_area_root二叉树来查找第一个区域first vm_area,然后根据这个first vm_area去查找vmap_area_list链表中满足大小的空间区域。

alloc_vmap_area函数中,有几个全局的变量:

static struct rb_node *free_vmap_cache;
static unsigned long cached_hole_size;
static unsigned long cached_vstart;
static unsigned long cached_align;

用于缓存上一次分配成功的vmap_area,其中cached_hole_size用于记录缓存vmap_area对应区域之前的空洞的大小。缓存机制当然也是为了提高分配的效率。

3.2 vunmap

vunmap执行的是跟vmap相反的过程:从vmap_area_root/vmap_area_list中查找vmap_area区域,取消页表映射,再从vmap_area_root/vmap_area_list中删除掉vmap_area,页面返还给伙伴系统等。由于映射关系有改动,因此还需要进行TLB的刷新,频繁的TLB刷新会降低性能,因此将其延迟进行处理,因此称为lazy tlb

来看看逆过程的流程:

4. vmalloc/vfree分析

4.1 vmalloc

vmalloc用于分配一个大的连续虚拟地址空间,该空间在物理上不连续的,因此也就不能用作DMA缓冲区。vmalloc分配的线性地址区域,在文章开头的图片中也描述了:VMALLOC_START ~ VMALLOC_END

直接分析调用流程:

从过程中可以看出,vmallocvmap的操作,大部分的逻辑操作是一样的,比如从VMALLOC_START ~ VMALLOC_END区域之间查找并分配vmap_area, 比如对虚拟地址和物理页框进行映射关系的建立。不同之处,在于vmap建立映射时,page是函数传入进来的,而vmalloc是通过调用alloc_page接口向Buddy System申请分配的。

  • vmalloc VS kmalloc
    到现在,我们应该能清楚vmallockmalloc的差异了吧,kmalloc会根据申请的大小来选择基于slub分配器或者基于Buddy System来申请连续的物理内存。而vmalloc则是通过alloc_page申请order = 0的页面,再映射到连续的虚拟空间中,物理地址不连续,此外vmalloc可以休眠,不应在中断处理程序中使用。
    vmalloc相比,kmalloc使用ZONE_DMA和ZONE_NORMAL空间,性能更快,缺点是连续物理内存空间的分配容易带来碎片问题,让碎片的管理变得困难。

4.2 vfree

直接上代码:

void vfree(const void *addr)
{BUG_ON(in_nmi());kmemleak_free(addr);if (!addr)return;if (unlikely(in_interrupt()))__vfree_deferred(addr);else__vunmap(addr, 1);
}

如果在中断上下文中,则推迟释放,否则直接调用__vunmap,所以它的逻辑基本和vunmap一致,不再赘述了。

【原创】(十二)Linux内存管理之vmap与vmalloc相关推荐

  1. 1709 ltsb 内存占用_「正点原子STM32Mini板资料连载」第三十二章 内存管理实验

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十二章 内存管理实验 上一章,我 ...

  2. 《Linux内核设计与实现》读书笔记(十二)- 内存管理

    内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己来解决(用户空间的内存错误可以抛给内核来解决). 所有内核的内存管理必须要简洁而且高效. 主要内容: 内存的管理单元 获取内存的方法 ...

  3. 正点原子的内存管理_正点原子【STM32-F407探索者】第四十二章 内存管理实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 上一章,我们学会了使用 STM32F4 驱动外部 SRA ...

  4. linux 内存管理之kmalloc、vmalloc、malloc、get_gree_pages的区别

    简述: 1.kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存 2.kmalloc保证分配的内存在物理上是连续的,内存只有在要被DMA访问的时候才需要物理上连续,mal ...

  5. linux内存管理分析 二,linux内存管理分析【二】

    为建立内存管理系统,在内核初始化过程中调用了下面几个函数: init/main.c asmlinkage void __init start_kernel(void) { ...... 初始化持久映射 ...

  6. linux cma内存,【原创】(十六)Linux内存管理之CMA,

    [原创](十六)Linux内存管理之CMA, 背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. ...

  7. Linux内存page,【原创】(十四)Linux内存管理之page fault处理

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  8. linux内存管理页面,【原创】(七)Linux内存管理 - zoned page frame allocator - 2

    [原创](七)Linux内存管理 - zoned page frame allocator - 2 背景 Read the fucking source code! --By 鲁迅 A picture ...

  9. 高端内存映射之kmap持久内核映射--Linux内存管理(二十)

    日期 内核版本 架构 作者 GitHub CSDN 2016-09-29 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 在内 ...

最新文章

  1. Linux命令grep
  2. Java 使用线程池ThreadPool:newFixedThreadPool
  3. centos升级python_CentOS 升级Python3
  4. mass Framework event模块 v8
  5. 高等数学同济第七版上册电子版_高等数学同济第七版(上册)第一章答案
  6. linux还原系统_怎么成为一名合格的Linux运维工程师
  7. 苹果要悄悄对这个产品动手了?你们最期盼的NFC功能也要来?
  8. android 实现抽屉效果
  9. Ubuntu系统详细分析【1-10】
  10. 全志平台BSP裁剪(3)附件二 Kernel hacking配置说明
  11. pythonhello world欢迎某某某同学_【第四章】python基本语法学习与练习题(慕课网习题)...
  12. 基于LMS及FxLMS算法的ANC主动降噪仿真分析
  13. 计算机报名照片最小像素高宽,网上报名照片如何确定大小
  14. 高考证件照要求什么底色
  15. 生产者消费者3.0 阻塞队列版本
  16. mysql删除学生记录_mysql删除重复记录语句,删除除了 id 号不同,其他都相同的学生冗余信息...
  17. 【Unity】Unity内存管理与优化(一)内存域、堆栈、垃圾回收、内存泄漏、内存碎片
  18. 算法:通过克鲁斯卡尔(Kruskal)算法,求出图的最小生成树
  19. phprm=20161221
  20. 银行卡怎么突然收不到短信信息服务器,银行卡开通了短信通知功能为什么没收到通知?十条原因看清楚...

热门文章

  1. 网站是如何跟踪监视你的
  2. 在Ubuntu 13.10 下安装支持SSL的Apache
  3. 全排列及相关扩展算法(六)——全排列最蛋疼的算法:邻位对换法
  4. 斗地主AI算法——第十三章の主动出牌(2)
  5. dd命令安装Linux
  6. 实例变量与局部变量的区别 java 1615135277
  7. 综合演练 实现登陆功能 1124
  8. linux-vim-文本编辑
  9. python-循环控制-break
  10. bootstrap-干货小结