任何程序最终都只会产生指令和数据。
在上图环境中,当程序加载到内存中运行时,Linux系统会给当前进程分配一个2^32大小的空间。
该空间主要分为两块:
- 用户空间(user space)
- 内核空间(kernal space)
两块空间共占用4G大小的空间,虚拟地址为0x00000000至0xFFFFFFFF,分隔点为0xC0000000。
程序运行时,程序的用户空间是(程序)私有的,内核空间是公共的。
用户空间
程序运行时的用户空间从低地址到高地址主要分为如下几块:
- 系统保留区/不可读区
- 代码段(.text)和只读数据段(.rodata)
- 数据段(.data)
- 数据段(.bss)
- 堆区(.heap)
- 加载共享库(*.dll/*.so)
- 栈区(stack)
- 命令行参数和环境变量
系统保留区存放着操作系统的预留的内容,不可访问,如空指针nullptr。
代码段存放着程序的指令,只读数据段存放着一些字符串常量。
数据段(.data)存放着程序已经初始化且初始值不为0的全局变量和静态变量。
数据段(.bss)存放着程序未初始化或者初始化为0的全局变量和静态变量。
堆区用于程序运行时的动态内存申请,空间较大,从低地址向高地址方向增长。该空间在程序运行时系统不会自动管理,申请的内存用完需要手动释放。
加载共享库主要用于存放系统运行时需要加载进来的共享库。
栈区用于程序中的函数运行,空间相对栈区较小,且从高地址向低地址增长。该空间在程序运行时由系统自动管理,申请的内存不需要手动释放。较大的函数或者无休止的递归函数容易导致栈溢出。
内核空间
程序运行时的内核空间从低地址到高地址主要分为如下几块:
- ZONE_DMA
- ZONE_NORMAL
- ZONE_HIGHMEM
参考资料
施磊老师C++基础课程;
《深入了解计算机原理》第7章
留言