前言
这里说的是 内核中分配按页分配的场景
常用于 驱动什么的, 分配 中大型空间
由于 连续的 n 个页是分别使用 alloc_pages 分配的, 因此是 虚拟地址空间连续, 但是 物理地址空间不连续
如何分配对象
两个步骤, __get_vm_area_node 获取为 size 分配的 vma 区间, 然后 __vmalloc_area_node 为给定的 vma 分配 n 个物理页
首先是定位查询可用空间的起点
free_vmap_cache 的作用是顺序分配的时候快速的定位 first
否则需要从 vmap_area_root 开始, 找到第一个大于 vmalloc 区间的 vma, 然后开始向后查询, 如果没有找到 使用 vstart 作为起始地址[vmalloc区间的第一块空间]
从 first 开始向后查询, 查询第一块空闲的可以容下 size 的空间, 来分配空间
如果是遍历到 vmap_area_list[是维护了虚拟地址顺序的] 的末尾, 以最后一块 vma 的 end 作为起始地址
找到空间 之后判断是否 overflow, 如果 overflow 走清理空间, 然后重试的处理
然后以 [addr, addr+size)作为当前待分配的 vma 的空间, 然后将 vma 添加到 vmap_area_root 上面, 以及将添加到 vmap_area_list 中[按照虚拟地址排序]
purge_vmap_area_lazy
寻找 vmap_purge_list 的地址空间的区间, 如果没有待释放的 vma, 直接返回
否则 以此 __free_vmap_area, 更新统计信息
从 vmap_area_root 中删除当前 vma, 从 vmap_area_list 中删除当前 vma
__vmalloc_area_node 计算 size 所需要的物理页的数量
然后循环 alloc_pages 分配物理页, 并和 vma 建立关联, 注册页表关联 等等
如何释放空间
remove_vm_area 为将 addr 对应的 vma 添加到 vmap_purge_list, 移除相关注册的 页表关联
__free_pages 清理掉关联的相关物理页
真实的 vma 相关数据的清理是在 xxx_purge_vmap_area_xx 相关函数中具体去实现
将当前 vma 添加到 vmap_purge_list, 如果超过了 阈值, 则直接 try_purge_vmap_area_lazy 清理空间
否则是在 分配空间的时候, vma 不够的时候 会 purge_vmap_area_lazy 清理空间
完