4G的虚拟内存空间:
其中1G是属于内核空间,另外的3G属于用户空间
所有的进程都拥有属于自己的用户空间,但却共享一个内核空间
3G用户空间:
1、保留区
保留区128M,我们通常将申请的临时指针变量初始化时置为NULL,可以防止后续无意使用这个指针出错,因为NULL == 0x0,将其指针指向0x0这个地址时,因为0x0这个地址属于保留区,没有访问权限的。
备注:保留区地址段内,在红帽子系统测试中C库在此区域,有数据段和代码段,
测试方法:cat proc/pid/maps
2、.text段
指令段:通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
3、.data段
数据段(data segment)通常是指用来存放程序中已始化且不为0的全局变量和静态变量的一块内存区域。数据段属于静态内存分配。常量也放在这个区域。
4、.bss段
数据段:(Bss Segment)通常是指用来存放程序中未初始化或者初始化为0的全局变量的一块内存区域,在程序载入时由内核清0。bss段属于静态内存分配。
PS:.data段与.bss段的区别(为什么有两个数据段)
1) BSS段不占用物理文件尺寸,但占用内存空间;数据段占用物理文件,也占用内存空间。所以有两个数据段节省文件空间。
对于大型数组如int ar0[10000] = {1, 2, 3, ...}和int ar1[10000],ar1放在BSS段,只记录共有10000*4个字节需要初始化为0,而不是像ar0那样记录每个数据1、2、3...,此时BSS为目标文件所节省的磁盘空间相当可观。
2) 当程序读取数据段的数据时,系统会出发缺页故障,从而分配相应的物理内存;当程序读取BSS段的数据时,内核会将其转到一个全零页面,不会发生缺页故障,也不会为其分配相应的物理内存。
5、heap
堆:一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,堆区域执行了malloc才存在
保存函数内部动态分配内存,是另外一种用来保存程序信息的数据结构,更准确的说是保存程序的动态变量。堆是“先进先出”数据结构。它只允许在堆的一端插入数据,在另一端移走数据。堆的地址空间“向上增加”,即当堆上保存的数据越多,堆的地址就越高。
6、共享库
在编写程序时,会依靠其他人已经写好的许多代码来执行例程或特殊功能。 这些代码存储在共享库中使用它们,需要将它们与自己的代码相链接,无论是在构建程序时还是在运行程序时。
7、stack
栈,由编译器自动分配释放,行为类似数据结构中的栈(先进后出)。
栈主要有三个用途:
①函数的返回地址(以便从被调用者返回)和参数
②存放临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量
③保存上下文:包括在函数调用前后需要保持不变的寄存器
8、命令行参数
int main()//这是我们平常写的main函数
{
}
int main(int argc, char *argv[],char *envp[])//这是真实的main函数
{
}
int argc表示命令行参数的个数(包括可执行程序名本身),char *argv[]表示每个参数的具体内容,argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,
9、环境变量
例:int execve(char *pathname,char* argv[],char*envp[]) ,char*envp就是所谓的环境变量
在我们调用一些系统库函数的时候,我们需要使用预处理指令#include。但是我们系统怎么知道去哪个路径寻找这些头文件的函数定义呢?就是通过char *envp[](环境变量)来实现的。
1G内核空间:
作用:Linux 操作系统和驱动程序运行在内核空间
物理地址 = 逻辑地址 – 0xC0000000:这是内核地址空间的地址转换关系,注意内核的虚拟地址在“高端”,但是ta映射的物理内存地址在低端。
①:内存直接访问(ZONE_DMA(大约16MB))
全名ZONE_DirectMemoryAccess(直接内存访问),可以加快磁盘和内存之间数据的交换,不需要经过CPU的寄存器,这时CPU可以去干别的事,大大增加了效率。
②:常用区域(ZONE_NORMAL)
内核中最重要最常用的部分。用于直接映射。PCB就在这里。
③:ZONE_HIGHMEM (128MB)
所谓的高端内存,用于在内核中映射高于1G的物理内存时使用。64位系统则没有该段(根本不需要,因为64位操作系统给内核空间分配的内存达到512G)。
内存分配方式:
(1) 从静态存储区域分配 。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量、static 变量 。
(2) 在栈区分配:相关代码执行时创建,执行结束时被自动释放。局部变量在此存储。栈内存分配运算内置于处理器的指令集中,效率高,但容量有限。
(3)在堆区分配:动态分配内存。用new/malloc时开辟,delete/free时释放。生存期由用户指定,灵活。但有内存泄露等问题。
内存泄漏情况详情见:https://mp.csdn.net/postedit/97110709
参考博客:https://blog.csdn.net/FoXiShaoNv/article/details/84261197