linux内核内存分配(三、虚拟内存管理)
在分析虚拟内存管理前要先看下linux内核内存的具体分配我開始就是困在这个地方。对内核内存的分类不是非常清晰。我摘录当中的一段:
内核内存地址
===========================================================================================================
在linux的内存管理中,用户使用0~3GB的地址空间。而内核仅仅是用了3GB~4GB区间的地址空间。共1GB。非连
续空间的物理映射就位于3GB~4GB之间。例如以下图示
0GB 3GB 4GB
而关于内核空间中这1GB是怎样分配的呢,详细请看下图:
一般会把内核空间中大于896M的空间称作内核空间中的高端内存。内核能够用三种不同的机制将页框映射到高端
内存:永久内核映射、暂时内核映射和非连续内存分配。本文中将要谈论的是非连续内存分配。
从上图能够知道,在物理内存的末尾和非连续内存区之间插入了一个大小为8MB的区间,这是一个安全区,
目的是“捕获”对非连续区的非法訪问。出于相同的理由。在其他非连续区间也插入了大小为4KB的安全区。而每一个
非连续区的大小都是4KB的倍数。例如以下图:
非连续内存的线性地址空间是从VMALLOC_START~VMALLOC_END,共128MB大小。
当内核须要用vmalloc类的函数
进行非连续内存分配时,就会申请一个vm_struct结构来描写叙述相应的vmalloc区,若分配多个vmalloc的内存区,那
么相邻两个vmalloc区之间的间隔大小至少为4KB,即至少是一个页框大小PAGE——SIZE。如上图。
===============================================================================================================
这里强调下:上面的图示表示的不过虚拟地址,而实际的物理地址是分DMA和常规地址及高端地址的;
linux内核内存大概的就是上面的图示了。当中8MB说是为了安全。防止越界訪问(看了非常多书,都这么说),就是这8MB虚拟地址不做不论什么映射(这样不过虚拟地址。没有实际的物理地址浪费)
由上面的图示能够知道,前面896MB(其它架构能够能不是以896MB切割的)就是我们说的内核逻辑地址(记住是内核逻辑地址。假设就说逻辑地址的话应该是指x86架构中虚拟地址中不包含段地址部分,也就是段内偏移部分);这部分内存地址已经在系统初始化的时候和物理页做好了映射,并且是一一映射,我们一般使用的时候就是用该部分的内存地址(kmalloc函数使用就是该部分)。这段内存是很高效的,由于不须要做其它的映射和改动页表就能够直接使用。本blog是分析下虚拟内存地址的映射,主要是vmalloc函数和ioremap函数;
vmalloc函数
vmalloc函数是驱动模块常常使用的内存分配函数。该函数返回的虚拟地址连续的(事实上这也有疑问。由于上面vmalloc的虚拟地址区有4k切割地址,假设vmalloc分配的虚拟地址非常大。那么中间是否有4kb的切割地址?),可是不保证所映射的物理地址也是连续的。
它主要对上面的vmalloc_start到vmalloc_end这段内存操作,返回的虚拟地址就是这一部分的。
在大多数情况下,不鼓舞使用vmalloc来申请内存,原因: 1、通过vmalloc函数获取的内存使用效率不高(由于要自己做映射,要推断哪些是空暇页等操作)。2、有些架构上给vmalloc使用的内存地址很小。对vmalloc调用可能会由于没有空暇地址而失败;3、不能保证物理地址是连续的,对一些驱动程序来说这是硬伤;综上所述。最好不要用包括vmalloc的代码作为内核的主线代码。
以下大概来说下vmalloc函数的原型:
void *vmalloc(unsigned long size);
该函数的实现有3个步骤:1、在vmalloc区域分配一段连续的虚拟内存地址;2、通过伙伴系统获取物理页;3、通过对页表的操作。把1中获取到的虚拟地址映射到2中分配到物理页上;
注意:
1、上面的图示我们能够看出每一个vmalloc虚拟地址之间都有4kb的切割区域(其作用就是防止越界。形成一个空洞,越界时产生异常),所以vmalloc函数实现时,会在size对齐后再添加4kb大小(一个页的大小)。
2、在分配物理页时,会从高端地址(上面的图示表示的不过虚拟地址而已,物理内存分配能够看linux内核内存分配(一、基本概念)中物理页和虚拟地址的映射图)分配。gfp为:GFB_KERNEL | _GFP_HIGHMEM;表示该函数可能睡眠,分配的物理地址来自高端物理页。
常规物理页给kmalloc使用;vmalloc函数分配高端物理页时使用alloc_page函数或者alloc_pages_node函数来分配一个整页,多次调用分配函数来完毕全部的物理页的分配,这样就不能保证全部的物理页一定连续了。
3、对虚拟地址映射时不会对额外的4k的切割地址进行映射,第2步中也不会对这4k的虚拟切割地址进行分配映射的物理页。
以下是vmalloc的映射图。图来自《深入linux设备驱动程序内核机制》
上图中:从vmalloc区域分配的两个虚拟页地址映射到物理地址的高端页面。当中高端内存是不连续的,虚拟地址最后一个页没有进行映射,那就是额外的4k切割页面。
用vmalloc分配得到的地址是不能在微处理器之外使用的。由于它们仅仅在处理器的内存管理单元上才有意义。
使用vmalloc函数的正确场合是在分配一大块连续的、仅仅在软件中存在的、用于缓冲的内存区域的时候。
ioremap函数
函数原型:void __iomem *ioremap(unsigned long phys_addr, size_t size);此处的__iomem仅仅是标识返回的地址是io类型的地址;该函数用来把vmalloc区域之间的内存映射到设备I/O地址空间,这个函数和vmalloc函数的实现很相似,不同的地方就是vmalloc是通过伙伴系统分配到物理页。而ioremap函数却是利用设备的I/O空间,而不是系统物理页;至于其它操作能够看:訪问I/O内存和I/Oport设备
ioremap函数很多其它用于映射(物理的)PCI缓冲区地址到(虚拟的)内核空间。ioremap函数映射的内存须要用iounmap函数来释放;
vmalloc和kmalloc比較
kmalloc函数:
1、得到的内存保留上次使用的数据,不正确申请到的内存进行初始化(zmalloc函数会初始化申请到的内存)。
2、返回的逻辑地址(事实上也是虚拟地址)和映射的物理页都是连续的。调用该函数时可能会休眠;
3、kmalloc函数和__get_free_pages函数返回的内存地址都是虚拟地址,事实上际的物理地址须要通过MMU转换后得到(事实上MMU就是通过页表机制来转换的)。
4、kmalloc函数和__get_free_pages函数使用的虚拟地址范围与物理内存是一一相应的,可能有个常量偏移。这两个函数不须要改动页表。
5、kmalloc函数申请的内存大小是有限制的,一般依据架构决定;
vmalloc函数和ioremap函数:
1、使用效率不高,物理页不保证连续,虚拟地址保证连续。
2、vmalloc函数和ioremap函数使用的地址范围全然是虚拟的。每次分配都要通过对页表的操作来建立映射关系;
3、vmalloc函数一般用来分配大块的内存。而且返回的地址不能在微处理器之外使用;
转载地址:http://blog.csdn.net/yuzhihui_no1/article/details/47429411
linux内核内存分配(三、虚拟内存管理)的更多相关文章
- linux内核内存分配(一、基本概念)
内存分配是Linux比较复杂也是比较重要的部分,这个和ssd驱动很类似:物理地址和虚拟地址的映射关系.下面总结下最近看到的有关内存分配的内容和自己的理解: 1.一致内存访问和非一致内存访问 上图来自& ...
- Linux内核分析(三)----初识linux内存管理子系统
原文:Linux内核分析(三)----初识linux内存管理子系统 Linux内核分析(三) 昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linu ...
- 十天学Linux内核之第三天---内存管理方式
原文:十天学Linux内核之第三天---内存管理方式 昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今 ...
- linux内核--内存管理(二)
一.进程与内存 所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内 ...
- Linux内核内存管理算法Buddy和Slab: /proc/meminfo、/proc/buddyinfo、/proc/slabinfo
slabtop cat /proc/slabinfo # name <active_objs> <num_objs> <objsize> <objpersla ...
- LINUX内核内存屏障
================= LINUX内核内存屏障 ================= By ...
- Linux内核设计第三周——构造一个简单的Linux系统
Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...
- linux内核分析第三周
20135103王海宁 linux内核分析第三周 http://mooc.study.163.com/course/USTC-1000029000 按照课堂提供的方法,命令行一行行敲上去,我是手机缓 ...
- 20135327郭皓--Linux内核分析第三周 构造一个简单的Linux系统MenuOS
Linux内核分析第三周 构造一个简单的Linux系统MenuOS 前提回顾 1.计算机是如何工作的三个法宝 1.存储程序计算机 2.函数调用堆栈 3.中断 2.操作系统的两把宝剑 中断上下文的切换 ...
随机推荐
- sqlserver2017安装及连接过程中发现的问题
1.SSMS安装报错,如下图 根据搜索资料发现是防火墙的问题,关闭防火墙就行了. 2.连接用户时报错 这个是因为远程连接相关问题. 首先打开服务器远程连接: 其次点击: SqlServer配置管理器- ...
- Git 使用中显示“Another git process seems to be running in this repository...”问题解决
一.引言:问题回忆 这几天,我同时在使用vs2017自带的git管理工具和git bash命令行工具对于同一个工作区进行了git操作管理. 其中,当我在vs2017中对文件进行了更改,突然脑洞大开,想 ...
- 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理
题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...
- selenium_UI自动化——篇1(基础)
元素定位的几种方式: (1)driver.find_element_by_id("idname") (2)driver.find_element_by_name("nam ...
- loj6253/luogu4062-Yazid的新生舞会
先考虑部分分(只有01/只有0~7)做法:枚举每个数,把和他相同的设为1,不同的设为-1,然后这个数作为众数贡献的个数就是区间和>0的个数 推着做,树状数组记前缀和<=x的区间的数量就可以 ...
- 51nod 1667 概率好题
Description: 甲乙进行比赛. 他们各有k1,k2个集合[Li,Ri] 每次随机从他们拥有的每个集合中都取出一个数 S1=sigma甲取出的数,S2同理 若S1>S2甲胜 若S1=S2 ...
- P3932 浮游大陆的68号岛
P3932 浮游大陆的68号岛 妖精仓库的储物点可以看做在一个数轴上.每一个储物点会有一些东西,同时他们之间存在距离. 每次他们会选出一个小妖精,然后剩下的人找到区间[l,r]储物点的所有东西,清点完 ...
- Java基础-hashMap原理剖析
Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...
- 转----MarkdownPad2.5 注册码
经测试可用 User: Soar360@live.com 授权: GBPduHjWfJU1mZqcPM3BikjYKF6xKhlKIys3i1MU2eJHqWGImDHzWdD6xhMNLGVpbP2 ...
- django2.0 官方中文文档地址
django2.0 官方开始发布中文文档了,之前还想着一直翻译完成所有有必要的内容,想着可以省事一些了,打开以后看了一下,发现官方的中文文档还没翻译完成, 现在(2018-7-10)最新章节是是 编 ...