掌握进程虚拟地址空间划分

前言

众所周知,任何的编程语言都会产生两种东西:数据和指令。那么拿我们c++代码来看,编译链接完成之后在我们Windows上来说会产生一个xxx.exe的可执行文件,现在这个文件放在我们磁盘上,那么cpu肯定是不能直接运行磁盘上的程序的,那么在运行它的时候首先会把这个程序从磁盘上加载到内存当中,那么就涉及到几个问题:

  1. 这一个可执行程序的哪些东西将会加载到内存当中?
  2. 加载到内存当中他是如何存放的?
  3. 内存有没有区域的划分?
  4. 4.划分了以后到底是什么样子?

首先我们得搞清楚一点,加载到内存是不可能直接加载到物理内存里!!!
拿我们当前的学习环境为例:在x86 32位Linux环境下
当我们的程序加载到内存的时候首先Linux系统会给当前进程分配一个2^32^大小的一块空间 也就是4G。这个空间我们定义为进程的虚拟地址空间那么这个虚拟我们该怎么理解了?IBM是这么解释的:
它存在,你能看的见,它是物理的;
它存在,你看不见,它是透明的;
它不存在,你却看得见,它是虚拟的;
它不存在,你也看不见,他被删除了;
但是一定要记住虚拟内存和虚拟地址空间不能记混了。

进程的虚拟地址空间:

在这里插入图片描述

用户空间:
  1. 指令都会放在.text段,这个是只读数据段
  2. 只读数据段.rodata一般存放常量字符串
  3. 前两者都是只能读不能写
  4. .data是专门存放初始化且不为0的数据。
  5. .bss段是存放未初始化的以及初始化为0的数据。当我们在全局的作用域里面去写一个全局变量没有初始化时,打印它的值得时候是一个0,这就是因为它存放在.bss段,我们的操作系统会自己负责把.bss段的数据全部置成0,所以这也就是我们为什么看到未初始化的全局变量我们去拓印它的值得时候是0的原因。
  6. 我们程序运行以后了,当我们调用了new 、malloc才会分配堆内存,堆内存从低地址向高地址增长。
  7. 当前程序在运行的过程中会加载一些共享库,也就是动态链接库:windows下就是.dll,Linux下就是so。
    6.在我们程序运行中函数运行或产生线程时每一个独有的stack(栈空间)。且栈是从高地址向低地址进行增长。

主函数内的普通变量不会生成符号,而是生成指令,存放在.text段,主函数内的静态局部变量遵循前面的规律。

内核空间:

  1. ZONE_DMA 大概16M的大小。
  2. ZONE_NORMAL 大概有800多M,进程空间的PCB块进程控制块都在里面存放,以及内核空间的线程还有内核函数在运行时所依赖的栈空间。
  3. ZONE_HIGHMEM 这是映射我们高地址的物理内存的时候做地址映射用的。

注意每一个进程的用户空间是私有的但是内核空间是共享的。

参考

施磊 腾讯课堂

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值