文章插图
上面介绍的这些全局变量和静态变量都是在编译期间就确定的 , 但是我们程序在运行期间往往需要动态的申请内存 , 所以在虚拟内存空间中也需要一块区域来存放这些动态申请的内存 , 这块区域就叫做堆 。注意这里的堆指的是 OS 堆并不是 JVM 中的堆 。
文章插图
除此之外 , 我们的程序在运行过程中还需要依赖动态链接库 , 这些动态链接库以 .so 文件的形式存放在磁盘中 , 比如 C 程序中的 glibc , 里边对系统调用进行了封装 。glibc 库里提供的用于动态申请堆内存的 malloc 函数就是对系统调用 sbrk 和 mmap 的封装 。这些动态链接库也有自己的对应的代码段 , 数据段 , BSS 段 , 也需要一起被加载进内存中 。
还有用于内存文件映射的系统调用 mmap , 会将文件与内存进行映射 , 那么映射的这块内存(虚拟内存)也需要在虚拟地址空间中有一块区域存储 。
这些动态链接库中的代码段 , 数据段 , BSS 段 , 以及通过 mmap 系统调用映射的共享内存区 , 在虚拟内存空间的存储区域叫做文件映射与匿名映射区 。
文章插图
最后我们在程序运行的时候总该要调用各种函数吧 , 那么调用函数过程中使用到的局部变量和函数参数也需要一块内存区域来保存 。这一块区域在虚拟内存空间中叫做栈 。
文章插图
现在进程的虚拟内存空间所包含的主要区域 , 笔者就为大家介绍完了 , 我们看到内核根据进程运行的过程中所需要不同种类的数据而为其开辟了对应的地址空间 。分别为:
- 用于存放进程程序二进制文件中的机器指令的代码段
- 用于存放程序二进制文件中定义的全局变量和静态变量的数据段和 BSS 段 。
- 用于在程序运行过程中动态申请内存的堆 。
- 用于存放动态链接库以及内存映射区域的文件映射与匿名映射区 。
- 用于存放函数调用过程中的局部变量和函数参数的栈 。
4. Linux 进程虚拟内存空间在上小节中我们介绍了进程虚拟内存空间中各个内存区域的一个大概分布 , 在此基础之上 , 本小节笔者就带大家分别从 32 位 和 64 位机器上看下在 Linux 系统中进程虚拟内存空间的真实分布情况 。
4.1 32 位机器上进程虚拟内存空间分布在 32 位机器上 , 指针的寻址范围为 2^32 , 所能表达的虚拟内存空间为 4 GB 。所以在 32 位机器上进程的虚拟内存地址范围为:0x0000 0000 - 0xFFFF FFFF 。
其中用户态虚拟内存空间为 3 GB , 虚拟内存地址范围为:0x0000 0000 - 0xC000 000。
内核态虚拟内存空间为 1 GB , 虚拟内存地址范围为:0xC000 000 - 0xFFFF FFFF 。
文章插图
但是用户态虚拟内存空间中的代码段并不是从 0x0000 0000 地址开始的 , 而是从 0x0804 8000 地址开始 。
经验总结扩展阅读
- 神话中高要一步一步往上爬是第几集?
- 神话一步一步爬到最高是几集?
- 总以为她会永远陪我一步一步慢慢走是什么歌
- 爱情不会一步到位而是会经过颇多挫折才圆满的星座
- Dubbo 03: 直连式 + 接口工程
- 一篇文章带你了解热门版本控制系统——Git
- 一篇文章带你了解网页框架——Vue简单入门
- 一直在等待爱却不敢主动迈出一步的星座
- 我用canvas带你看一场流星雨
- 一篇文章带你掌握MyBatis简化框架——MyBatisPlus