linux进程内存中按低地址到高地址,Linux进程内存分布

进程内存分布

之前一直在分析栈,栈这个东西的作用也介绍得差不多了,但是栈在哪儿还没有搞清楚,以及堆、代码、全局变量它们在哪儿,这都牵涉到进程的内存分布。

linux 0.01 的进程内存分布

内存分布随着操作系统的更新换代,越来越科学合理,也越来越复杂,所以我们还是先了解一下早期操作系统的典型 linux 0.01 的进程的内存分布:

linux 0.01 的一个进程固定拥有64MB的线性内存空间(ACM竞赛中单个程序的最大内存占用限制为64MB,这肯定有猫腻O(∩_∩)O~),各个进程挨个放置在一张页目录表中,一个页目录表可管理4G的线性空间,因此 linux0.01 最多有 64个进程。每个进程的内存分布如下:

9afd7dcd806eb15fc7fea008a45a491c.png

.text 里存的是机器码序列

.rodata 里存的是源字符串等只读内容

.data 里存的是初始化的全局变量

.bss 上一篇介绍过了,存的是未初始化的全局变量

堆、栈就不用介绍了吧!

【注意】static 变量未初始化默认赋值为0或者空格。未初始化变量和初始化为0,都分配在.bss段。

.text .rodata .data .bss 是常驻内存的,也就是说进程从开始运行到进程僵死它们一直蹲在那里,所以访问它们用的是常量地址;而栈是不断的加帧(函数调用)、减帧(函数返回)的,帧内的局部变量只能用相对于当前 esp(指向栈顶)或 ebp(指向当前帧)的相对地址来访问。

栈被放置在高地址也是有原因的: 调用函数(加帧)是减 esp 的,函数返回(减帧)是加 esp 的,调用在前,所以栈是向低地址扩展的,放在高地址再合适不过了。

现代操作系统的进程内存分布

认识了 linux 0.01 的内存分布后,再看看现代操作系统的内存分布发生了什么变化:

首先,linux 0.01 进程的64MB内存限制太过时了,现在的程序都有潜力使用到 2GB、3GB 的内存空间(每个进程一张页目录表),当然,机器有硬伤的话也没办法,我的电脑就只有 2GB 的内存,想用 3GB 的内存是没指望了。但也不是有4GB内存就可以用4GB(32位),因为操作系统还要占个坑呢!现代 linux 中 0xC0000000 以上的 1GB 空间是操作系统专用的,而 linux 0.01 中第1个 64MB 是操作系统的坑,所以别的进程完全占有它们的 64MB,也不用跟操作系统客气。

其次,linux 0.01只有进程没有线程,但是现代 linux 有多线程了(linux 的线程其实是个轻量级的进程),一个进程的多个线程之间共享全局变量、堆、打开的文件…… 但栈是不能共享的:栈中各层函数帧代表着一条执行线索,一个线程是一条执行线索,所以每个线程独占一个栈,而这些栈又都必须在所属进程的内存空间中。

根据以上两点,进程的内存分布就变成了下面这个样子:

d3e8e194d8170ebb78b77e2cc1772082.png

再者,如果把动态装载的动态链接库也考虑进去的话,上面的分布图将会更加"破碎"。

如果我们的程序没有采用多线程的话,一般可以简单地认为它的内存分布模型是 linux 0.01 的那种。

========================

一个linux进程分为几个部分(从一个进程的地址空间的低地址向高地址增长):

1.text段,就是存放代码,可读可执行不可写,也称为正文段,代码段。

2.data段,存放已初始化的全局变量和已初始化的static变量(不管是局部static变量还是全局static变量)

3.bss段,存放全局未初始化变量和未初始化的static变量(也是不区分局部还是全局static变量)

以上这3部分是确定的,也就是不同的程序,以上3部分的大小都各不相同,因程序而异,若未初始化的全局变量定义的多了,那么bss区就大点,反之则小点。

4.heap,也就是堆,堆在进程空间中是自低地址向高地址增长,你在程序中通过动态申请得到的内存空间(c中一般为malloc/free,c++中一般为new/delete),就是在堆中动态分配的。

5.stack,栈,程序中每个函数中的局部变量,都是存放在栈中,栈是自高地址向低地址增长的。起初,堆和栈之间有很大一段空间,然后随着,程序的运行,堆不断向高地址增长,栈不断向高地址增长,这样,堆跟栈之间的空间总有一个最大界限,超过这个最大界限,就会出现堆跟栈重叠,就会出错,所以一般来说,Linux下的进程都有其最大空间的。

6.再往上,也就是一个进程地址空间的顶部,存放了命令行参数和环境变量。

整个进程地址空间布局如下图所示:

baa80c52837142b13ddccac240e08330.png

程序运行开始,由系统为进程地址空间中的text/data/bss段进行映射,由系统的缺页异常处理程序按需将磁盘上程序文件中的真正代码、数据写入进程。此外,bss区域中的所有变量都会被清零。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值