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 ...
随机推荐
- Linux下C语言的调试
调试是每个程序员都会面临的问题. 如何提高程序员的调试效率, 更好更快地定位程序中的问题从而加快程序开发的进度, 是大家共同面对的问题. 可能Windows用户顺口就会说出:用VC呗 :-) , 它提 ...
- Python操作Word:常用对象介绍
前面已经介绍过了试用win32com类库来进行Word开发,系列文章<Python操作Word>是继承了前面的文章,所以,你应该先查看前面的文章,其实只有两篇,文章地址列在最下面的参考资料 ...
- linux - camera capture
//cut a picture#include <stdio.h>#include <stdlib.h>#include <string.h>#include &l ...
- js获取字符串的实际长度并截断实际长度
在项目中有这样一个需求,就是一个很长的字符串,需要截断成几组字符串,而这几组字符串里既包含汉字,又包含字母,下面提供了几种方法 1,获取字符串的长度 function getstrlength(str ...
- struts2 OGNL ValueStack概念理解 # % $ 的区别
http://blog.csdn.net/tjujacob/article/details/8117659 —————————————————————————————————————————————— ...
- ci 框架插入时返回插入的id号
$this->db->insert('goods',$data); $gid=$this->db->insert_id('goods'); return $gid;
- Reveal Jquery 模式对话框插件
/* * jQuery Reveal Plugin 1.0 * www.ZURB.com * Copyright 2010, ZURB * Free to use under the MIT lice ...
- JS 拖动原理
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 关于Unity的组件和作用
一.Transform组件 整个场景由节点树组成. 节点+Transform组件,每个Transform有自己的孩子Transform,由Transform组成Transform树,而每个Transf ...
- 【BZOJ】1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典(dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=1633 一开始也想到了状态f[i]表示i以后的字符串最少删的数 然后想到的转移是 f[i]=min{f ...