LInux进程虚拟地址空间的管理
2017-04-07
脱离物理内存的管理,今天咱们来聊聊进程虚拟内存的管理。因为进程直接分配和使用的都是虚拟内存,而物理内存则是有系统“按需”分配给进程,在进程看来,只知道虚拟内存的存在!
前言:
关于虚拟内存和物理内存这些东东,本篇不作介绍,此等基础知识参考最普通的操作系统参考书籍即可。当然有问题也可留言,我们共同学习,共同进步!
进程虚拟地址空间:
每个进程拥有一个独立的虚拟地址空间,独立怎么体现?进程A有个地址1000,进程B也有个地址1000,为何两个地址不发生矛盾,还能正常工作,这就是独立性的体现。原来,两个相同的虚拟地址会经过自己所属进程的页表,转化成不同的物理地址。只要实际的物理地址不发生冲突,就没有关系。这一切怎么实现的呢?自然需要内核去维护。内核为每个进程维护一套页表,页表实现虚拟地址到物理地址的转换,其基地址存储在CR3寄存器中,是物理地址。x86架构下,地址线是32根,那么就可以寻址到2^32个地址,因为默认都是按字节寻址,所以虚拟地址空间就为2^32字节即4GB,64位额CPU使用48根地址线,虚拟地址空间更大。本文不做虚拟地址空间深入分析,旨在介绍虚拟地址空间是怎么使用的。
虚拟地址空间的划分:
每个进程都有自己的虚拟地址空间,但是也不能随意使用,还是需要规划好的,毕竟内存时比较稀缺的资源,咱们必须本着可持续发展的战略去使用。很明显,进程运行过程中需要的信息都要装入内存,那么进程运行期间都需要哪些信息呢?
- 程序运行代码的二进制代码。
- 程序使用的动态库的代码。
- 存储全局变量和动态产生数据的堆。
- 保存局部变量和实现函数过程调用的栈。
- 环境换量和命令行参数的段。
- 将文件内容映射到虚拟地址空间的的内存映射。
进程虚拟地址空间映射结构如下两种结构,在地址空间不富裕的情况下,前者比较合适。
进程的3GB空间安排大致如图所示,最底下是映射的可执行文件的映像,一般包含代码段和数据段。数据段中包含有全局变量和静态数据的空间。再往上就是堆空间,这里堆空间和MMAP区域是相对生长的,从而充分利用这些地址空间。MMAP区域上边是栈空间,而栈空间上面不使用了,所以栈一般位于进程地址空间的顶部。一般情况下栈的最高地址是用户空间可用的最高地址,当指定栈随机化时,会空闲一个随机大小,这样可在一定程度上,对栈实施保护。
每个进程结构有一个mm_struct结构管理该进程的地址空间,每个分配的内存块由一个vm_area_struct结构表示,所有的vm_area_struct结构构成一个红黑树,树根保存在mm_struct中的mm_rb字段。这点和windows的进程地址空间管理十分类似,windows下采用的是VAD树,也是个二叉树。在vm_area_struct结构中记录该内存块的起始和结束地址,同一个进程的所有vm_area_struct结构还会连接成一个链表,开始于mm_struct 中的mmap。总体来讲进程地址空间的分配主要涉及三部分:进程可执行文件的映射、堆栈的分配、MMAP区域的分配。
进程可执行文件的映射
可执行文件映射在图中的text段,这里text段包含代码、数据。代码自然是程序自身的代码,而数据就是一些常量,全局数据区,静态数据区等。具体映射方式需要根据ELF文件的格式,所以映射的细节我们不做详细介绍。当可执行文件的映像映射到进程的虚拟地址空间时,产生一组vm_area_struct结构,相当于还没执行之前,可执行文件已经被划分成了虚拟页面,由vm_area_struct管理。待程序执行时会根据vm_area_struct结构和物理内存建立映射并填充页表项,具体参见pagefault处理流程。
堆栈的分配
堆栈在程序运行时动态分配,二者的用途不同。堆主要用于动态内存的分配,可分配比较大的内存块,且必须主动申请分配,使用完后需要手动释放如malloc、new(malloc在分配更大的内存会在MMAP区域)。而栈有程序自动分配,有系统负责回收,且栈的大小一般受限,常分配比较小的内存块。
MMAP区域
MMAP 区域位于堆和栈之间,用于映射文件内容到进程虚拟地址空间。注意这里是虚拟地址空间而不是物理地址空间。 每个文件在内核对应一个inode节点,inode节点的 i_mapping字段是address_space类型,记录当前文件到进程地址空间的映射情况。address_space结构中关联了映射的内存区域vm_area_struct,私有和共享映射通过红黑树管理,而非线性映射通过链表管理。进程每打开一个文件,内核会使用一个file结构记录本次打开的情况,file结构通过f_mapping字段指向文件对应的address_space,这样进程和文件的联系就建立起来了。具体联系如下
我们提到的映射都是映射的是文件到进程虚拟地址空间,不牵涉物理地址。具体物理地址的映射由内存管理单元负责,当进程对文件发起读写操作时,最终会根据文件描述符定位到其address_space,根据address_space得到要读写的页,此时页具备虚拟地址,通过对虚拟地址进行读写发生pagefault,此时当前进程就被迫陷入到内核异常处理流程,pagefault处理流程就把本次需要的页调入内存,然后返回到用户空间继续刚才进程的运行,这里其实进程本身并感知不到缺页,它仅仅负责从文件读,具体缺页由CPU感知且处理。关于MMAP其实设计的东西很多,这里不再深入介绍,回头重开一篇文章单独讲述MMAP机制。
参考资料:LInux内核3.10.1源码、深入LInux内核架构
LInux进程虚拟地址空间的管理的更多相关文章
- Linux进程虚拟地址空间管理2
2017-04-12 前篇文章对Linux进程地址空间的布局以及各个部分的功能做了简要介绍,本文主要对各个部分的具体使用做下简要分析,主要涉及三个方面:1.MMAP文件的映射过程 2.用户 内存的动态 ...
- linux进程虚拟地址空间
转载源 在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中.这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存地址块.在Linux系统中, ...
- linux进程的地址空间,核心栈,用户栈,内核线程
linux进程的地址空间,核心栈,用户栈,内核线程 地址空间: 32位linux系统上,进程的地址空间为4G,包括1G的内核地址空间,和3G的用户地址空间. 内核栈: 进程控制块task_struct ...
- linux进程的介绍和管理
概述 - 在linux 中,每个执行的程序都称为一个进程,每一个进程都分配一个ID号 - 每一个进程,都会对应一个父进程,而这个父进程可以复制多个子进程,例如www服务器 - 每个进程都可 ...
- Linux进程地址管理之mm_struct
FROM : http://www.cnblogs.com/Rofael/archive/2013/04/13/3019153.html Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进 ...
- Linux 基础 —— Linux 进程的管理与监控
这篇文章主要讲 Linux 中进程的概念和进程的管理工具.原文:http://liaoph.com/inux-process-management/ 进程的概念 什么是进程 进程(Process)是计 ...
- linux进程地址空间--vma的基本操作【转】
转自:http://blog.csdn.net/vanbreaker/article/details/7855007 版权声明:本文为博主原创文章,未经博主允许不得转载. 在32位的系统上,线性地址空 ...
- linux 进程地址空间的一步步探究
我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间 ...
- Linux了解进程的地址空间
供Linux了解虚拟内存,非常好的引导了.原文链接:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26683523&i ...
随机推荐
- 高效学习Oracle的方法论
Oracle的很多经验并不是来自工业环境.很多问题和经验都可以从自己的测试里积累 实验要做,但也要想! 那思维的起点是什么? 以下是我的看法.或者有些不合理: ...
- js 開始时间,当前时间,结束时间的比較
//開始时间不能小于当前时间 function startTimeIsBigThanTotay(startTime){ var startdate = new Date((startTime).rep ...
- TCP状态图
TCP建立关闭连接状态图 MSL:Max segment lifetime最大段存活时间. MSL在RFC1122中规定为两分钟,但是各个操作系统的实现不同,在linux上一般配置MSL???? 处于 ...
- [算法]滴滴笔试题——求最大子串和(O(n)复杂度)
扫描法.一次扫描数组即可得出答案,复杂度O(n).这种方法用文字描述不容易说清楚,下面用每一步运算的图示来表达.伪代码如下: maxsofar=end=; ,n) end=max(end+x[i],) ...
- 原生js怎么删除一个 div
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Ubuntu 16.04 更换阿里云源
Ubuntu 16.04 更换阿里云源sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak #备份sudo gedit /etc/apt/so ...
- 007杰信-factory的启用+停用
业务需求:当有一些factory与我们不在合作时,我们不能直接删除这个公司的数据,我们采用的办法是在factory_c表增加一个字段STATE(CHAR(1)),1表示是启用,0是表示停用. 准备工作 ...
- Try中如果发现错误,即跳出try去匹配catch,那么try后面的语句就不会被执行
例:public void print() throws Exception. 对于方法a,如果它定义了throws Exception.那么当它调用的方法b返回异常对象时,方法a并不处理,而将这个异 ...
- 嵌入式开发之gb281818
http://www.cnblogs.com/snake-hand/p/3157176.html http://blog.csdn.net/voipmaker/article/category/140 ...
- socket udp广播和多播的简单实现
UDP广播与多播 作者:legend QQ:1327706646 使用UDP协议进行信息的传输之前不需要建议连接.换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信 ...