【UNIX】从一个可执行文件的生成到进程在内存中分布 (下)/进程的内存分布

从一个可执行文件的生成到进程在内存中分布 (下)

                                                                              进程的内存分布


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

 

当一个可执行文件静态的存储在物理内存空间时,我们没考虑太多关于可执行文件存储在物理内存中是怎么分布存储的以及相关的地址信息,这些被静态编译的文件都是以固定的格式存放于不同的存储介质中,只有相对地址的概念,当我们在编译、链接的时候,编译器会根据具体的链接脚本,把可执行文件的各个目标文件模块的相关信息以段的方式有效整合的链接到对应的内存空间中,这里我们就要考虑到对于CPU来说,要处理相关的指令是根据指令的地址信息来取指的。还有要注意的是(一个程序的链接地址就是虚拟地址,而运行地址就是物理地址,这就要涉及到物理地址和虚拟地址的转换问题,它是通过MMU内存管理单元来实现的

当涉及到地址相关的操作,我们就应该弄清楚进程是在内存空间怎么分布的问题以及一个进程的一般有哪些部分

【UNIX】从一个可执行文件的生成到进程在内存中分布 (下)/进程的内存分布_第1张图片【UNIX】从一个可执行文件的生成到进程在内存中分布 (下)/进程的内存分布_第2张图片

 

bss段:

BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。


data段:

数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。


text段:

代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。


rodata段:

存放C中的字符串和#define定义的常量


heap堆:

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)


stack栈:

是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。


常量段:

常量段一般包含编译器产生的数据(与只读段包含用户定义的只读数据不同)。比如说由一个语句a=2+3编译器把2+3编译期就算出5,存成常量5在常量段中

 

特别注意:

1)text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;

2)bss段不在可执行文件中,由系统初始化。

3)bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小具体体现为一个占位符

4).bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);

而.data却需要占用,其内容由程序初始化

 

 


你可能感兴趣的:(Linux)