1. Linux内存空间分布
(图片来自:代码随想录)
包括程序的二进制可执行代码,只读;TEXT
包括已初始化的全局变量和静态常量;DATA
包括未初始化的静态变量和全局变量;BSS
包括动态分配的内存,从低地址开始向上增长;
包括动态库、共享内存等,从低地址开始向上增长 (跟硬件和内核版本有关) ;
包括函数的参数值和局部变量、函数调用的上下文等。栈的大小是固定的,一般是 8 MB 。当然系统也提供了参数,以便我们自定义大小;栈区是从高地址位向低地址位增长的。
2. Linux虚拟内存
(1)基本概念
对32位处理器,虚拟内存空间为4G,每个进程都认为自己拥有4G的空间(对于上面的内存分布图,虚拟内存使得每个进程都认为自己独占那样一段内存),实际上,在虚拟内存对应的物理内存上,可能只对应的一点点的物理内存。
进程得到的这4G虚拟内存是一个连续的地址空间(这也只是进程认为),而实际上,它通常是被分隔成多个物理内存碎片,还有一部分存储在外部磁盘存储器上,在需要时进行数据交换
由于存在两个内存地址,因此一个应用程序从编写到被执行,需要进行两次映射。第一次是映射到虚拟内存空间,第二次时映射到物理内存空间。在计算机系统中,第两次映射的工作是由硬件和软件共同来完成的。承担这个任务的硬件部分叫做存储管理单元 MMU(Memory Management Unit),软件部分就是操作系统的内存管理模块了。
虚拟内存是一种实现在计算机软硬件之间的内存管理技术,它将程序使用到的内存地址(虚拟地址)映射到计算机内存中的物理地址,虚拟内存使得应用程序从繁琐的管理内存空间任务中解放出来,提高了内存隔离带来的安全性,虚拟内存地址通常是连续的地址空间,由操作系统的内存管理模块控制,在触发缺页中断时利用分页技术将实际的物理内存分配给虚拟内存,而且64位机器虚拟内存的空间大小远超出实际物理内存的大小,使得进程可以使用比物理内存大小更多的内存空间。
(2)如何处理虚拟地址和物理地址的关系
当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
(图片来自:代码随想录)
虚拟地址分为: 页号和页内偏移。
页号作为页表的索引,页表包含物理页每页所在物理内存的基地址,这个基地址与页内偏移的组合就形成了物理内存地址。