进程虚拟地址空间划分和布局

        任何的编程语言写出的代码都会二种东西:指令数据

        C++代码在编译链接完成后会产生一个可执行文件放到磁盘上面,程序需要从磁盘上加载到内存中才能运行。那么可执行文件的哪些东西加载到内存中呢?加载到内存中又是如何存放呢?内存区域如何划分的呢?而加载到内存也不是直接加载到物理内存而是虚拟内存。我们学习的环境是Linux下32位,所以程序运行加载到内存时候,内核会给当前进程分配2的32次方的虚拟内存空间,也就是4G,这块空间也叫进程的虚拟地址空间。从底层原理来说,虚拟地址空间只是内核创建的一系列数据结构而已。在32位的Linux下面, 系统默认内核空间是占1G,用户空间占3G。0到3G是用户空间, 3G到4G是内核空间。可以通过修改操作系统的配置来更改用户空间和内核空间的比例。而在用户空间并没有从0地址开始存放 内容,而是前面空了一段空间从0x08048000开始存放我们的内容。空的这段空间是预留的,不能读写也不能访问。如果访问这一块空间,那么程序就会报异常崩溃。从0x08048000开始就是代码段(.text),指令在运行时候存放在这一块区域。这段里面通常还会有.rodata,也就是只读代码段。比如函数里面定义的"hello world"。.rodata和.text都是只读不能写,一写程序就崩溃。接下来就是数据段(.data),存放程序运行中的数据。然后边上是.bss段,也叫数据段。这二段有什么不同呢? .data段存放初始化了的而且初始值不为0的数据,.bss段存放未初始化全局变量和初始化值为0的数据

        在程序中,定义一个未初始化的全局变量,当我们打印的时候发现他是0.因为程序运行的时候,内核给当前进程分配空间,未初始化的数据存放在.bss段,操作系统会将.bss段的全部数据清0.

        然后就是堆(.heap),这块是空的,当程序运行过程中调用malloc或者new时候就在这分配内存。

        再接着就是程序运行过程中加载的动态链接库(比如Linux下面的.so库和windows下面的.DLL)

        接下来就是栈空间,(函数运行过程中或者产生线程时候,线程在当前进程私有的空间也只有栈)

        栈和堆的增长方向是相反的。接下来就是存放命令行参数和环境变量的空间

        内核空间分为ZONE_DMA,有16MB大小;ZONE_NORMAL大概有800多MB,这里面存放进程控制块task_struct结构体,还有内核空间的线程和内核函数在运行时候需要的栈空间都在这部分ZONE_HIGHMEM是一块高端内存,做地址映射用的。

         全局变量不管是普通的还是静态的都叫数据这些数据编译后都会在符号表中产生符号,这叫数据。全局变量都是初始化了且初始化不为0,那么存放在.data段,未初始化或者初始化为0的全局变量,会存放在.bss段,其中未初始化的变量在程序运行前会被操作系统清0.

         而函数中的局部变量不会产生符号,它们对应生成的是指令。比如在x86体系下面,int a = 12;生成指令就是mov dword ptr[a],0ch ; 所以三个函数中的局部变量的定义最终生成的是三个mov指令,指令存放在.text段中

        而函数中的局部静态变量在程序启动的时候是不会初始化的,局部静态变量是在程序第一次运行到他们的时候才进行初始化,e初始化不为0,所以放在.data段,而f和g放在.bss段。这时候如果打印c这个局部变量,肯定不为0,它是栈上的无效值。但如果打印g会是0,因为g在.bss段存放,操作系统在程序运行时候会把.bss段清0.

        注意:这里有一个概念性的错误!!!常规我们知道局部变量是存放在栈中,为什么这里定义局部变量是生成指令呢?首先abc三个局部变量的定义经过编译后产生的指令存放在.text代码段的,但是当这个函数运行时候,系统会在当前进程的栈上给这个函数开辟一块栈帧,所以那三个局部变量编译后的指令运行后,会在栈空间上开辟内存存放局部变量

        注意:每一个进程的用户空间是私有的,但是内核空间是共享的。比如下面多个进程都有自己的用户空间,但是他们的内核空间是共享的。

 当然内核空间存放的就是操作系统内核运行的数据结构,每个进程都有自己的用户空间。那么比如进程之间的通信方式有哪些?进程和进程之间通信比较难,原因是进程的用户空间是隔离的,但是内核空间是共享的。所以所谓的匿名管道通信就是在内核空间中 开辟一块内存,这样一个进程在这块内存中写数据其他进程就能够看见了,因为内核空间是共享的

int gdata1 = 10;
int gdata2 = 0;
int gdata3;

static int gdata4 = 11;
static int gdata5 = 0;
static int gdata6;
int main(){
    int a = 12;
    int b = 0;
    int c;
    static int e = 13;
    static int f  = 0;
    static int g ;
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值