专栏首页人人都是极客Linux 内存管理之vmalloc

Linux 内存管理之vmalloc

走进vmalloc

根据前面的系列文章,我们知道了buddy system是基于页框分配器,kmalloc是基于slab分配器,而且这些分配的地址都是物理内存连续的。但是随着碎片化的积累,连续物理内存的分配就会变得困难,对于那些非DMA访问,不一定非要连续物理内存的话完全可以像malloc那样,将不连续的物理内存页框映射到连续的虚拟地址空间中,这就是vmap的来源)(提供把离散的page映射到连续的虚拟地址空间),vmalloc的分配就是基于这个机制来实现的。

vmalloc最小分配一个page,并且分配到的页面不保证是连续的,因为vmalloc内部调用alloc_page多次分配单个页面。

vmalloc的区域就是在上图中VMALLOC_START - VMALLOC_END之间,可通过/proc/vmallocinfo查看。

数据结构

  • vmap_area 描述一段虚拟地址的区域,可以将struct vm_struct构成一个链表,维护多段映射。
struct vmap_area {
 unsigned long va_start; //vmalloc申请虚拟地址返回的起始地址
 unsigned long va_end; //vmalloc申请申请虚拟地址返回的结束地址
 unsigned long flags;
  //挂接到vmap_area_root红黑树
 struct rb_node rb_node;         /* address sorted rbtree */
  //挂接到vmap_area_list链表
 struct list_head list;          /* address sorted list */
 struct llist_node purge_list;    /* "lazy purge" list */
 //如果当前VA处于使用状态(即在vmap_area_root为根的红黑树中和vmap_area_list链表中),vm有效,指向用于管理虚拟地址和物理页之间的映射关系的描述符
 struct vm_struct *vm;
 struct rcu_head rcu_head;
};
  • vm_struct 管理虚拟地址和物理页之间的映射关系
struct vm_struct {
 struct vm_struct *next; //指向下一个vm结构体
 void   *addr; //当前vmalloc区域的虚拟地址的起始地址
 unsigned long  size; //当前vmalloc区域的虚拟地址的大小
 unsigned long  flags;
 //vamlloc分配获取的各个物理页面并是不连续的,每个物理页面用struct page描述,一个vm_struct对用到的管理所有物理页面的struct page构成一个数组,而pages就是指向这个数组的指针。
 struct page  **pages;
 unsigned int  nr_pages; //vmalloc映射的page数目
 phys_addr_t  phys_addr; //用来映射硬件设备的IO共享内存,其他情况下为0
 const void  *caller; //调用vmalloc函数的函数的地址
};

vmalloc

主要分以下三步:

  1. 从VMALLOC_START到VMALLOC_END查找空闲的虚拟地址空间(hole)
  2. 根据分配的size,调用alloc_page依次分配单个页面.
  3. 把分配的单个页面,映射到第一步中找到的连续的虚拟地址。把分配的单个页面,映射到第一步中找到的连续的虚拟地址。

本文分享自微信公众号 - 人人都是极客(rrgeek),作者:布道师Peter

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-04-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 高端内存映射之vmalloc分配内存中不连续的页--Linux内存管理(十九)

    根据上文的讲述, 我们知道物理上连续的映射对内核是最好的, 但并不总能成功地使用. 在分配一大块内存时, 可能竭尽全力也无法找到连续的内存块.

    233333
  • vmalloc原理与实现

    在 Linux 系统中的每个进程都有独立 4GB 内存空间,而 Linux 把这 4GB 内存空间划分为用户内存空间(0 ~ 3GB)和内核内存空间(3GB ~...

    用户7686797
  • Linux内核设备驱动之内存管理笔记整理

    到目前为止,内存管理是unix内核中最复杂的活动。我们简单介绍一下内存管理,并通过实例说明如何在内核态获得内存。

    砸漏
  • Linux 内存管理之CMA

    CMA是reserved的一块内存,用于分配连续的大块内存。当设备驱动不用时,内存管理系统将该区域用于分配和管理可移动类型页面;当设备驱动使用时,此时已经分配的...

    刘盼
  • Linux内存描述之高端内存--Linux内存管理(五)

    过去,CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了...

    233333
  • 别再说你不懂Linux内存管理了,10张图给你安排的明明白白!

    对于精通 CURD 的业务同学,内存管理好像离我们很远,但这个知识点虽然冷门(估计很多人学完根本就没机会用上)但绝对是基础中的基础。

    程序IT圈
  • Linux内存描述之概述--Linux内存管理(一)

    传统的多核运算是使用SMP(Symmetric Multi-Processor )模式:将多个处理器与一个集中的存储器和I/O总线相连。所有处理器只能访问同一个...

    233333
  • Linux内存描述之内存区域zone--Linux内存管理(三)

    为了支持NUMA模型,也即CPU对不同内存单元的访问时间可能不同,此时系统的物理内存被划分为几个节点(node), 一个node对应一个内存簇bank,即每个内...

    233333
  • Linux内存描述之内存页面page--Linux内存管理(四)

    分页单元可以实现把线性地址转换为物理地址, 为了效率起见, 线性地址被分为固定长度为单位的组, 称为”页”, 页内部的线性地址被映射到连续的物理地址. 这样内核...

    233333

扫码关注云+社区

领取腾讯云代金券