进程的内存布局

 

Linux内存管理机制

    Linux的内存管理主要由两个部分组成,一个部分负责物理内存的申请与释放,物理内存的申请与释放最小单位与Windows一样,都是以"页"为单位,在IA32中页的大小是4 KB;另外一个部分负责处理虚拟内存,虚拟内存的操作主要包括虚拟地址空间与实际存储空间的映射,物理内存页与硬盘页之间的置换等,下面各节分别介绍这几个方面的内容。

进程的内存布局

    一个32位Linux进程的地址空间为4 GB,与Windows类似,这个4 GB空间并不能全部被一个Linux进程的用户空间代码使用,而是有一部分留给了内核。但与Windows不同,Linux中4 GB的高位1 GB空间留给了内核,低位的3 GB由进程用户代码使用,如图5-7所示。

0X00000000~0XBFFFFFFF这一3 GB区域为用户地址空间,而上面的0XC0000000 ~ 0XFFFFFFFF这一1 GB区域保留给内核使用。用户地址空间进一步被分成程序代码区、数据区(包括初始化数据区DATA和未初始化数据区BSS)、堆和栈。程序代码区占据最底端,紧接着往上为数据区,先是初始化数据区,然后是未初始化数据区。代码区中存放应用程序的机器代码,运行过程中代码不能被修改,因此代码区内存为只读,且大小固定。数据区中存放了应用程序中的全局数据,静态数据和一些常量字符串等。数据区的大小也是固定的。

 
图5-7  一个32位Linux进程的地址空间

    如图5-8所示,除了代码区,初始化数据区和未初始化数据区之外,还有两个动态增长和缩减的区域即堆和栈。

    堆从未初始化数据区开始,向上端动态增长,增长过程中虚拟地址值变大;而栈则从高位地址开始,向下端动态增长,虚拟地址值变小。

    堆是应用程序在运行过程中动态申请的内存空间,如开发人员通过malloc/new需要动态生成对象或者开辟内存空间时,最终会调用系统调用brk来动态调整数据区的大小。当这些动态内存区域使用完毕,需要开发人员明确使用相应的free/delete释放这些内存空间。free/delete最终也会调用到brk调整数据区的大小。

 
图5-8  堆和栈

    栈与堆有明显的区别,栈用来存放函数的传入参数、临时变量,以及返回地址等数据。这些数据不需要通过malloc/new来为之开辟内存空间,而且其增长与缩减是因为函数的调用与返回,而不必开发人员的额外操作。堆空间的维护不需要开发人员的参与,而且也没有内存泄漏的危险。

    初始化数据区和未初始化数据区还有一些值得注意的事情,初始化数据区存放的是那些在编译期就能够知道由程序设定初始值的全局变量及静态变量等。这些初始值必须保存在最终生成的二进制文件中,并且在程序运行时会原封不动地将这个区域映射到进程的初始化数据区域。当程序声明N个这样的初始化数据,且其空间占据M大小,那么在二进制文件中,就会开辟M大小的区域。即依次存放N个数据,且每个都设置了相应的初始值。当程序运行时,这块区域就会原封不动地映射到该对应进程的"初始化数据区"。"原封不动"意味着在二进制文件中这块区域的大小与进程虚拟地址空间中一样大,而且排列和对应地址的值也一样。

    但未初始化数据区则不如此,如果一个全局变量或者静态变量在源代码文件中没有被赋予初始值,那么在程序启动后,在第1次被赋值前,其初始值为0。即这些数据本质上还是有初始值的,只不过初始值为0。但是当最终生成二进制文件时,这些未初始化数据区并不会像初始化数据区那样,占据它们对应变量的总大小的区域,而只是用一个值来记录其总大小。比如,一个程序的代码指令有100 KB大小,所有的初始化数据总大小为100KB,所有的未初始化数据总大小为150 KB,那么在最终生成的二进制文件中,代码区会有100 KB。接着100 KB大小的初始化数据区,然后接着一个4个字节大小的空间,其值为150×1024(指示其大小为150 KB),注意,这里不是一个150 KB大小的所有单元值都为0的空间。这样可以节省二进制文件的大小,即节省硬盘空间。但是在进程虚拟地址空间中,对应于这一区域的未初始化数据区的大小必须是150 KB。因为在程序运行时,程序必须能够真正访问到这些变量中的每一个。这也意味着,当程序启动时,当监测到二进制文件中未初始化数据区的那个值为150×1024时,系统会开辟出一个150 kB大小的区域作为进程的未初始化数据区域并且同时用0来初始化这一区域。

 

http://book.51cto.com/art/201006/203601.htm

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值