linux非连续内存,linux高端内存管理之非连续内存区(分配和释放)
前面总结了非连续内存区域的内核描述,接着看看他的分配和释放。
一、非连续内存区的分配
不管是vmalloc()还是vmalloc_32()等系列的分配函数最后都会调用__vmalloc_node()函数实现,直接看这个函数的实现。
*__vmalloc_node - allocate virtually contiguous memory
*@size:allocation size
*@align:desired alignment
*@gfp_mask:flags for the page level allocator
*@prot:protection mask for the allocated pages
*@node:node to use for allocation or -1
*@caller:caller's return address
*
*Allocate enough pages to cover @size from the page level
*allocator with @gfp_mask flags. Map them into contiguous
*kernel virtual space, using a pagetable protection of @prot.
*/
static void *__vmalloc_node(unsigned long size, unsigned long align,
gfp_t gfp_mask, pgprot_t prot,
int node, void *caller)
{
struct vm_struct *area;
void *addr;
unsigned long real_size = size;
size = PAGE_ALIGN(size);
if (!size || (size >> PAGE_SHIFT) > totalram_pages)
return NULL;
/*分配相关的结构并对其初始化,在前面介绍过了*/
area = __get_vm_area_node(size, align, VM_ALLOC, VMALLOC_START,
VMALLOC_END, node, gfp_mask, caller);
if (!area)
return NULL;
/*分配物理空间,建立页表映射*/
addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
/*
* A ref_count = 3 is needed because the vm_struct and vmap_area
* structures allocated in the __get_vm_area_node() function contain
* references to the virtual address of the vmalloc'ed block.
*/
/*调试用*/
kmemleak_alloc(addr, real_size, 3, gfp_mask);
return addr;
}
struct page **pages;
unsigned int nr_pages, array_size, i;
/*需要减去一个页面,因为在分配结构的时候指定了多一个页面*/
nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT;
/*页面指针所占空间大小*/
array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages;
/* Please note that the recursion is strictly bounded. */
if (array_size > PAGE_SIZE) {/*如果页面指针空间大于一个页面时,这个空间用非连续内存分配*/
pages = __vmalloc_node(array_size, 1, gfp_mask | __GFP_ZERO,
PAGE_KERNEL, node, caller);
area->flags |= VM_VPAGES;
} else {/*如果页面指针空间所占大小小于一个页面时,用slab机制分配这个空间*/
pages = kmalloc_node(array_size,
(gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO,
node);
}
/*初始化area结构*/
area->pages = pages;
area->caller = caller;
if (!area->pages) {
remove_vm_area(area->addr);
kfree(area);
return NULL;
}
/*对每个页面调用分配函数分配物理空间,
也就是每次分配一个页面*/
for (i = 0; i < area->nr_pages; i++) {
struct page *page;
if (node < 0)/*分配物理页面空间*/
page = alloc_page(gfp_mask);
else
page = alloc_pages_node(node, gfp_mask, 0);
if (unlikely(!page)) {
/* Successfully allocated i pages, free them in __vunmap() */
area->nr_pages = i;
goto fail;
}
area->pages[i] = page;/*初始化area中page数组*/
}
/*因为非连续区间没有建立页表机制,在这里需要建立他*/
if (map_vm_area(area, prot, &pages))
goto fail;
return area->addr;/*返回线性地址*/
fail:
vfree(area->addr);
return NULL;
}
其中map_vm_area()建立页表映射机制的实现就是依次对pgd、pud、pmd、pte的设置。
二、非连续内存区的释放
调用vfree()函数实现
/**
*vfree - release memory allocated by vmalloc()
*@addr:memory base address
*
*Free the virtually continuous memory area starting at @addr, as
*obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
*NULL, no operation is performed.
*
*Must not be called in interrupt context.
*/
void vfree(const void *addr)
{
BUG_ON(in_interrupt());
/*调试用*/
kmemleak_free(addr);
/*释放工作*/
__vunmap(addr, 1);
}
static void __vunmap(const void *addr, int deallocate_pages)
{
struct vm_struct *area;
if (!addr)
return;
if ((PAGE_SIZE-1) & (unsigned long)addr) {
WARN(1, KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
return;
}
/*从vlist链表和红黑树中移除指定地址的线性区间*/
area = remove_vm_area(addr);
if (unlikely(!area)) {
WARN(1, KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n",
addr);
return;
}
debug_check_no_locks_freed(addr, area->size);
debug_check_no_obj_freed(addr, area->size);
if (deallocate_pages) {
int i;
for (i = 0; i < area->nr_pages; i++) {/*每次释放一个页面*/
struct page *page = area->pages[i];
BUG_ON(!page);
__free_page(page);
}
if (area->flags & VM_VPAGES)/*在创建非连续区间时,如果页面
指针所占的空间大于一个页面时,从非连续内存区间
中分配。所以这里也就从相应的释放*/
vfree(area->pages);
else
kfree(area->pages);/*从slab中释放*/
}
kfree(area);/*释放area*/
return;
}
/**
*remove_vm_area - find and remove a continuous kernel virtual area
*@addr:base address
*
*Search for the kernel VM area starting at @addr, and remove it.
*This function returns the found VM area, but using it is NOT safe
*on SMP machines, except for its size or flags.
*/
struct vm_struct *remove_vm_area(const void *addr)
{
struct vmap_area *va;
/*从红黑树种查找而不是链表,为了效率起见*/
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA) {
struct vm_struct *vm = va->private;
struct vm_struct *tmp, **p;
/*
* remove from list and disallow access to this vm_struct
* before unmap. (address range confliction is maintained by
* vmap.)
*/
write_lock(&vmlist_lock);
/*从链表中找到,然后删除*/
for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
;
*p = tmp->next;
write_unlock(&vmlist_lock);
/*调试用*/
vmap_debug_free_range(va->va_start, va->va_end);
/*从红黑树中删除*/
free_unmap_vmap_area(va);
vm->size -= PAGE_SIZE;
return vm;
}
return NULL;
}
总结:linux高端内存非连续区的整体描述以及其分配和释放基本就总结完了。总结的只是一个大概的原理框架,不过根据这个框架对细节的了解应该不难。另外,其中涉及到伙伴系统、slab机制等部分需要再做分析和总结。
linux非连续内存,linux高端内存管理之非连续内存区(分配和释放)相关推荐
- 【Linux】Linux的内核空间(低端内存、高端内存)
内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点. 内核空间与用户空间的关系 在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法就 ...
- showdialog 尝试读取或写入受保护的内存_轻松一键上4000MHz,XPG龙耀D50 重装RGB内存值不值得高端用户选购?...
随着今年intel.AMD.nvidia分别推出旗下的高端硬件产品迭代提升,处理器和显卡性能也迎来了新的飞跃,对不少游戏玩家等高端用户来说,有了强劲的硬件,还需要高频内存才能补齐短板,让整机性能再上一 ...
- win7计算机内存占用高,win7开机占用内存过高怎么回事?win7开机占用内存过高的处理方法...
一位用户反馈说win7系统开机加载时间非常长,占用内存无比之高,4G内存被吃掉了80%.电脑内存被占用从而影响我们的电脑运行速度,占用内存越多相对就会变得越慢.针对此问题,小编来和大家详解一下解决方法 ...
- 计算机开机内存占用80%,Win10开机后内存占用高80%以上怎么办_win10电脑开机内存占用高达80%以上如何解决...
近日有不少win10系统用户遇到这样一个现象,就是电脑开机之后,内存占用很费,达到了80%以上了,导致电脑非常卡,许多用户不知道遇到这样的该怎么办,为了解决这样的问题,接下来将给大家讲述一下win10 ...
- antimalware service executable占用内存过高_Win10系统svchost.exe进程占用内存和网速过高的解决方法...
我们在使用Windows10系统的过程中,不少用户一旦发现电脑异常,例如异常卡顿,就会查看一下任务管理器,是否有进程过高占用了CPU.内存.网络等,而在任务管理器中发现了一个名称为"svch ...
- 服务器内存使用率高找不到是哪个进程,内存占用率高,但是找不到内存消耗大的程序...
您好, window 8 对系统软硬件这块的要求相比之前的操作系统而言,可能会高,需要能够支持这块的软硬件或软硬件厂商的支持.我们也了解了下遇到该问题的其他用户,在window 8 开机后可能会有CP ...
- LM358(非轨道轨)高端电流采样 廉价充电指示方案
分析 : LM358选择普通国产方案, 几分钱一个,整体充电板五毛钱. 由于LM358是非轨道轨的, 在输入前先分压为原先的一半,若是轨对轨的运放,可以不用电阻做分压. 然后两个结果进入LM358放大 ...
- Linux内存管理之高端内存映射
一:引子 我们在前面分析过,在linux内存管理中,内核使用3G->4G的地址空间,总共1G的大小.而且有一部份用来做非连续空间的物理映射(vmalloc).除掉这部份空间之外,只留下896M大 ...
- Linux内存管理:内存描述之高端内存
<Linux内存管理:内存描述之内存节点node> <Linux内存管理:内存描述之内存区域zone> <Linux内存管理:内存描述之内存页面page> < ...
- 详谈Linux系统《高端内存和低端内存》
高端内存是Linux中一个重要的概念,初涉Linux时曾经对这个概念非常迷惑.实际上这个概念比较简单,理解这个概念,需要追溯一下Linux的内存管理. 从前,CPU的地址总线只有32位.32的地址总线 ...
最新文章
- MySQL数据库中文模糊检索问题
- 如何选专业选课题?姚期智院士:首先成为一名科学家
- ++i 和 i++ 效率分析(C++)
- hive 添加UDF(user define function) hive的insert语句
- Python的第三方库pyppeteer
- 目标检测——Anchor-Based算法的学习笔记
- 工具记录,使用jarsigner 对APK进行签名
- 在 Java 应用程序中定时执行任务
- word转pdf公式乱码_求助:Word转pdf时公式会公式变成乱码
- Eventlog Analyzer日志管理系统、日志分析工具、日志服务器的功能及作用
- 想要畅听全网音乐?试试 Listen1吧!
- 使用apt更新和升级系统软件
- 压力传感器如何直接连接电脑笔记本采集数据表格导出
- 改进灰色预测matlab代码,灰色预测模型Matlab代码[比赛已经用过,保真好使]
- 深入浅出TensorFlow2函数——tf.data.Dataset.padded_batch
- 中学生读以奋斗者为本有感3500字
- ML之PDP:机器学习可解释性之部分依赖图(Partial Dependence Plots)之每个特征如何影响您的预测?
- Ethernet(以太网) 物理介质(10Base、100Base-T、100Base-TX等)
- 数据库是啥?数据库的概念
- 暴风影音2018届校园招聘技术类笔试题目
热门文章
- python移动文件但不覆盖_怎么做到Python file重复写入之前的内容不被后写入的覆盖...
- BZOJ1864: [Zjoi2006]三色二叉树
- 《炬丰科技-半导体工艺》SC-1颗粒去除和piranha后漂洗的机理研究
- 为什么要推销自己_推销自己:为什么? 如何!
- 人人都在推销(销售永不为“奴”)
- vscode 中 php 代码格式化插件和其他设置
- Docker进阶实战
- 运用EXCEL RAND RANK INDEX函数制作抽奖器
- mysql实验报告4_实验四∶数据库安全性实验报告.doc
- uni-app第三方插件 根据银行卡卡号查询银行类型和卡类型