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

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

在阅读本文前大家需要明确,本文是在X86体系,32位Linux环境下进行描述的。
任何的编程语言在编译链接时都只会产生两种东西:指令和数据。编译链接后会产生一个可执行文件,存储在磁盘上,当然CPU是不可能直接运行磁盘上的程序的,还需要将磁盘上的程序加载到内存当中。那么,问题是将可执行文件中的哪些内容加载到内存当中呢?加载到内存当中后又是如何存放的?内存中有没有区域的划分,如果有,又是如何划分的呢?这些问题将在后续内容中进行讲解。
看这段代码:

#include<stdio.h>
int gdata1 = 10;
int gdata2 = 0;
int gdata3;

static int gdata4 = 11;
static int gdata5 = 0;
static int gdat6;

int main()
{
	int a = 12;
	int b = 0;
	int c;

	static int e = 13;
	static int f = 0;
	static int g;
	return 0;
}

在这段代码中定义了:
6个全局变量——分别是初始化不为0的全局变量gdata1、初始化为0的全局变量gdata2、未初始化的全局变量gdata3以及初始化不为0的静态全局变量gdata4、初始化为0的静态全局变量gdata5、未初始化的静态全局变量gdata6;
6个局部变量——分别是初始化不为0的局部变量a、初始化为0的局部变量b、未初始化的局部变量c以及初始化不为0的静态局部变量d、初始化为0的静态局部变量f、未初始化的静态局部变量g。
当程序运行时,Linux系统会给当前进程分配一个2^32(4G)大小的一块空间。该空间即为进程的虚拟地址空间。这个空间默认被划分为两个部分,分别为user space(用户空间)、kernal space(内核空间),其中用户空间分为预留区域、.text段(存放指令等,只读)、.rodata段(只读段)、.data段(存放初始化不为0的全局变量、初始化不为0的静态全局变量以及初始化不为0的静态局部变量).bss段(存放未初始化以及初始化为0的全局变量,并且会将未初始化的变量自动初始化为0)、.heap段(堆内存,当程序运行调用new或者malloc时,系统才会分配该空间,从低地址——>高地址增长)、加载动态链接库(windows下为*.dll,Linux为*so)、stack(栈空间,从高地址——>低地址增长)、命令行参数和环境变量。内核空间分为ZONE_DMA、ZONE_NORMAL、ZONE_HIGHMEM。如下图所示:
在这里插入图片描述
而我们刚才定义的变量的存储位置如下图所示:
在这里插入图片描述
阅读到这里,有读者也许会问局部变量a为什么不是存储在栈上,而变成了指令存储到了.text段呢?其实程序在编译链接运行时,在编译后局部变量a产生的是指令,当指令运行时CPU才会在栈上分配一个4字节的空间来存储局部变量的值12。
最后,还需要注意的是每一个进程的用户空间是私有的,而内核空间是共享的。
如图所示:
在这里插入图片描述
推荐书籍:深入理解计算机系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值