内存布局图:

来分析一下程序在内存中的分布情况:
假设这块长方形是一块虚拟的内存空间,那么它的大小有多大呢?有4G空间大小。
以32位操作系统为例,32位操作系统的最大寻址能力,也就是2的32次方字节,换算一下就是4个G大小。
我们大部分操作系统,拿到这一块4个G的内存空间之后都会帮做简单的划分。

比如第一部分拿出来留给内核来使用,至于这块空间是多大呢?不同的操作系统有不同的大小,Linux这个块空间分配了1G的大小空间,那么剩下的用户区就是3个G,而1G的内存空间这一块区域称为内核区,也就是内核空间。
内核空间主要存储以下内容:
1.内核代码
这是操作系统内核的可执行指令集,包含了实现进程管理、内存管理、设备驱动、文件系统等核心功能的代码,比如进程调度算法、内存分配与回收算法的代码。
2.内核数据结构
进程控制块(PCB):存储进程的各种信息,如进程ID、进程状态、优先级、程序计数器、寄存器值等,用于操作系统对进程进行管理和调度。
内存管理数据结构:像页表,用于实现虚拟地址到物理地址的映射,记录了进程的虚拟内存空间与物理内存页的对应关系;还有内存分配位图,用于标记物理内存中哪些页面已分配,哪些是空闲的。
文件系统数据结构:如索引节点(inode)表,存储了文件的元信息,包括文件的权限、所有者、大小、创建时间等,以及目录项结构,用于组织文件系统中的目录和文件。
3.内核栈
为内核线程和中断处理程序提供临时的存储区域,用于保存函数调用的返回地址、函数参数、局部变量等。比如在中断处理函数执行时,会将当前进程的相关寄存器值等压入内核栈,以便中断处理完成后能恢复到原来的执行状态。
4.共享数据区
用于内核与驱动程序以及不同内核模块之间共享数据和传递信息,比如内核与显卡驱动程序可能会通过共享数据区来传递显示参数、图形数据等。
5.设备驱动程序代码和数据
包含了各种硬件设备的驱动程序代码,以及驱动程序运行时所需的数据,如网卡驱动程序代码及网卡的配置信息、状态寄存器值等,使内核能够与硬件设备进行交互,实现设备的初始化、数据传输等操作。
主要看一下用户空间:
1.我们从最低位的地址0开始看起,有一段非常非常小的地址空间,它是系统保留区,它是0~255这么小的一块空间,这块空间可以忽略不计,这一块是保留区。
2.代码段,也叫文本段,存储着程序的可执行指令,是程序运行的核心部分。如C语言程序中函数的指令代码就存于此,通常为只读,防止程序运行时意外修改导致错误。
3.只读数据段,它存储我们程序中的常量,我们写的常量全部存储在这个段里面。
代码段和只读数据段,它们具有相同的读写属性,存的都是只读的数据。
4.初始化数据段,顾名思义就是存储我们系统中初始化的数据,也就是存储我们系统中已经初始化的全局变量。
5.未初始化数据段,.BSS未初始化数据段,里面存储的是我们未初始化的全局变量:包括初始化为默认值的全局变量,比如整形默认初始化是0,布尔类型默认初始化的false,这样的变量会存储在未初始化数据段里面。
6.堆区,堆中存放的是我们程序中动态分配的内存。堆栈之间还有一块数据区,这一块数据区叫做共享数据区。堆的内存如果增长的话,它是向上增长的,但是栈的内存它是向下增长的。
用于动态内存分配,由程序员通过malloc、new等操作申请和释放内存空间。
如int* ptr = (int*)malloc(sizeof(int));即在堆段分配了一块存储int类型数据的空间。
7.栈是程序运行中调用最频繁的区域。比如说存储函数的形参,局部变量。
总结一下:
用户空间分为代码段,只读数据段,初始化数据段和未初始化数据段,堆区,栈区。
.test代码,存储程序中可执行指令。
只读数据段,存的是程序中写的常量。
初始化数据段,存的是已经初始化的全局变量。
未初始化数据段,存储的是未初始化的全局变量。
堆区,存储程序运行中动态开辟的空间。
栈,存储的是函数形参,局部变量。