Linux进程地址空间和虚拟内存
一、虚拟内存
先来看一张图(来自《Linux内核完全剖析》),如下:
分段机制:即分成代码段,数据段,堆栈段。每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低特权级(用户),每当程序试图访问(权限又分为可读、可写和可执行)一个段时,当前特权级CPL就会与段的特权级进行比较,以确定是否有权限访问。每个特权级都有自己的程序栈,当程序从一个特权级切换到另一个特权级上执行时,堆栈段也随之改换到新级别的堆栈中。
段选择符:每个段都有一个段选择符。段描述符指明段的大小、访问权限和段的特权级、段类型以及段的第一个字节在线性地址空间中的位置(称为段的基地址)。而段选择符用于在描述符表中进行索引找到段描述符。
虚拟地址:虚拟地址的偏移量部分加上段的基地址上就可以定位段中某个字节的位置,即形成线性地址空间中的地址。
分页机制:当使用分页机制时,每个段被划分成页面(通常每页在4KB大小),页面会被存储于物理内存或硬盘上。如果禁用分页机制,那么线性地址空间就是物理地址空间。
当程序试图访问线性地址空间上的一个地址位置时,发生以下操作:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
if(数据在物理内存中)
{ 虚拟地址转换成物理地址 读数据 } else { if(数据在磁盘中) { if(物理内存还有空闲) { 把数据从磁盘中读到物理内存 虚拟地址转换成物理地址 读数据 } else { 把物理内存中某页的数据存入磁盘 把要读的数据从磁盘读到该页的物理内存中 虚拟地址转换成物理地址 读数据 } } else { 报错 } } |
其中MMU负责虚拟地址到物理地址的转换工作,分段和分页操作都使用驻留在内存中的段表和页表来指定他们各自的交换信息。如果用户程序想要访问一个虚拟地址,经MMU检查无权访问(特权级),MMU产生一个异常,CPU从用户模式切换到特权模式,跳转到内核代码中执行异常服务程序,内核把这个异常解释为段错误,把引发异常的进程终止掉。
二、linux进程地址空间
由前面可得知,进程有4G的寻址空间,其中第一部分为“用户空间”,用来映射其整个进程空间(0x0000 0000-0xBFFF FFFF)即3G字节的虚拟地址;第二部分为“系统空间”,用来映射(0xC000 0000-0xFFFF FFFF)1G字节的虚拟地址。如下图
将其更加详细地展示如下:
程序路径:完整的绝对路径字符串如 “/home/simba/code/asm/simple”
环境变量:类似linux下的PATH,HOME等的环境变量,子进程会继承父进程的环境变量。
命令行参数:类似ls -l 中-l 就是命令行参数,而ls 就是可执行程序。
栈:就是堆栈,程序运行时需要在这里做数据运算,存储临时数据,开辟函数栈等。在Linux下,栈是高地址往低地址增长的。
对于函数栈来说,函数运行完毕就释放内存,举例递归来说,一直开辟向下函数栈,然后由下往上收复,所以递归太多层的话很可能造成栈溢出。
局部变量(不包含静态变量);局部可读变量(const)都分配在栈上。
共享库和mmap内存映射区:比如很多程序都会用到的printf,函数共享库 printf.o 固定在某个物理内存位置上,让许多进程映射共享。mmap是个系统函数,可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。此外,调用malloc 时正常是调用brk 系统调用分配内存,特定条件下是调用mmap 来映射物理内存到进程地址空间。
堆:即malloc申请的内存,使用free释放,如果没有主动释放,在进程运行结束时也会被释放。
Text Segment: 可执行程序(二进制)(.text);全局初始化只读变量(const)(.rodata);字符串常量(.rodata);均在这里分配。
Data Segment: 全局变量(初始化的在.data,未初始化的在.bss);静态变量(全局和局部)(初始化的在.data,未初始化的在.bss);全局未初始化只读变量(.bss);均在这里分配。
Linux进程地址空间和虚拟内存相关推荐
- Linux进程地址空间学习总结
Linux内核--内核地址空间分布和进程地址空间 http://www.cnblogs.com/bizhu/archive/2012/10/09/2717303.html 内核地址空间分布 直接映射区 ...
- Linux进程地址空间与进程内存布局详解,内核空间与用户空间
Linux进程地址空间与进程内存布局详解 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初始化的数据. 未初始化过的数据( ...
- linux 进程 地址空间 内存分布 简介
目录 一 进程空间分布概述 二 内核空间和用户空间 三 进程内存布局 栈 内存映射段 堆 BBS和数据段 C语言程序实例 栈与堆的区别 一 进程空间分布概述 对于一个进程,其空间分布如下图所示: 程序 ...
- linux 进程地址空间的一步步探究
我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间 ...
- Linux 进程地址空间 进程内存布局
一 进程空间分布概述 对于一个进程,其空间分布如下图所示: 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初始化的 ...
- Linux进程地址空间探究
我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间 ...
- linux进程地址空间--vma的基本操作
在32位的系统上,线性地址空间可达到4GB,这4GB一般按照3:1的比例进行分配,也就是说用户进程享有前3GB线性地址空间,而内核独享最后1GB线性地址空间.由于虚拟内存的引入,每个进程都可拥有3GB ...
- Linux:进程地址空间管理(图文详解总结)
首先我们要明白一个概念:什么是地址? 地址是指向内存区域的一个编号,每一个进程都有4G的进程地址空间. 那么系统到底是如何给进程分配内存的呢? 结论:分页管理+虚拟地址空间 看图进一步理解 如上图是系 ...
- [入门篇]用史上最生动的方式让你一篇博客搞懂Linux进程地址空间,包看包懂!
目录 0.前言 1.初始程序的地址空间划分 1.1程序地址空间图解 1.2程序地址空间区域划分验证 1.3 程序地址空间小补充 1.4 引入进程地址空间 *2. 两个生动的例子理解进程地址空间 2.1 ...
最新文章
- 数字孪生城市应用【案例集】,附下载
- 编程的精髓:发现问题,解决问题
- linux ruby gem 安装目录,linux 安装 gem
- intx update task - IB_IBINTX_UPDATE
- Latex 中插入超链接 插入网址
- BitNami-Redmine1.1.0安装和VisualSVN-Server配合使用
- python读音Python怎么读
- css base64 图片背景
- SpringMVC的Model、Model Map、ModelAndView
- 开发工程师的职场人生路
- 2017年数学建模美赛个人国际一等奖论文
- 计算机锁定无法安装软件,无法安装软件是什么原因,Win10无法安装应用软件的处理方法...
- 友情链接加nofollow_如何在WordPress中添加Nofollow链接(适用于初学者的简单指南)
- PHP从基础到高级详细教程(完整版)
- 24道ES必知必会的面试题整理一波,从早上卷起来
- origin Pro 9.0画多条三维折线图(此处以两条为例)
- 什么是Hy? (官方文档翻译)
- 使用Python + Adb 实现对QQ实时点击名片赞,输入文本信息
- 人工神经网络建模步骤,人工神经网络模型定义
- 7 款最好的免费 PDF 转 Word 转换器工具
热门文章
- 蓝桥杯 ALGO-100 算法训练 整除问题
- [Java] 蓝桥杯 BEGIN-4 入门训练 Fibonacci数列
- 蓝桥杯 BASIC-5 基础练习 查找整数
- maven 排除某个类_java-如何从Maven依赖项中排除某些程序包(在JAR中)?
- Mysql 两种情况下更新字段中部分数据的方法
- 分享一个漂亮WPF界面框架创作过程及其源码
- Redis实现分布式锁2
- JavaScript错误信息
- 脑电波技术新突破:读心准确率达到95%
- fatal error LINK1123:failure during conversion to COFF:file invalid or corrupt