Linux 内存管理:虚拟内存空间布局

虚拟内存布局

Linux 内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。这样,进程就可以很方便地访问内存,更确切地说是访问虚拟内存。虚拟地址空间的内部又被分为内核空间用户空间两部分,

不同字长(也就是单个 CPU 指令可以处理数据的最大长度)的处理器,地址空间的范围也不同。32 位系统的内核空间占用 1G,位于最高处,剩下的 3G 是用户空间。而 64 位系统的内核空间和用户空间都是 128T,分别占据整个内存空间的最高和最低处,剩下的中间部分是未定义的。

Linux 内存管理:虚拟内存空间布局_第1张图片
image

用户态空间分布

用户空间主要用来存储如下数据:

  • 程序代码
  • 全局变量
  • 常量字符串
  • 函数栈,存放方法局部变量
  • 堆,申请一小块内存,存放在堆中
  • glibc关联函数代码
Linux 内存管理:虚拟内存空间布局_第2张图片
image

Text Segment

是存放二进制可执行代码的位置

Data Segment

存放静态常量,从高地址开始向下增长

BSS Segment

存放未初始化的静态变量

malloc函数申请一小块内存,存放在堆中,从低地址开始向上增长

mmap映射区

  • mmap用来存放malloc函数申请一大块内存区域,mmap不仅仅可以用来映射物理内存同时也可以用来映射文件,所谓映射文件就时将文件数据拷贝到物理内存中某个区域,这块区域通过页表映射到用户mmap映射区中。这样用户可以像访问内存一样访问文件。

  • 当mmap区域映射到文件时我们称为文件映射,非文件时称为匿名映射。

  • 当内存空间不足时可以将内存数据写入磁盘中的某个文件,这个过程称为换出,当进程访问这些内存时,再从磁盘读取这些数据到内存中这个过程称为换入。而这个写入的文件被称为swap文件

Linux 内存管理:虚拟内存空间布局_第3张图片
image

这块地址用来存放方法局部变量,从高地址开始向下增长

内核态空间分布

内核空间主要用来存储如下数据

  • 内核的代码要在内存里面;
  • 内核中也有全局变量;
  • 每个进程都要有一个 task_struct;
  • 每个进程还有一个内核栈;
  • 在内核里面也有动态分配的内存;
  • 虚拟地址到物理地址的映射表

内核态的虚拟空间和某一个进程没有关系,所有进程通过系统调用进入到内核之后,看到的虚拟地址空间都是一样的。在内核态,32 位和 64 位的布局差别比较大,主要是因为 32 位内核态空间太小了。

32位操作系统内核空间

Linux 内存管理:虚拟内存空间布局_第4张图片
image
直接映射区

直接映射区,就是这一块空间是连续的,和物理内存是非常简单的映射关系,直接宏函数就得到物理内存的位置,大小为896M,其中前 1M 已经在系统启动的时候被占用,1M之后到896M主要用来存储内核代码内核的全局变量内核栈

//运算规则 虚拟内存地址减去 3G,就得到物理内存的位置
__pa(vaddr) 返回与虚拟地址 vaddr 相关的物理地址;
__va(paddr) 则计算出对应于物理地址 paddr 的虚拟地址。
内核动态映射空间 vmalloc区

用来申请内核动态分配的内存(使用vmalloc函数)

持久内核映射

用来存储内核进程数据结构 task_struct

固定映射区域

主要用于满足特殊需求

最后区域

用户态的进程要映射一个文件到内存中,先要映射用户态进程空间的一段虚拟地址到物理内存,然后将文件内容写入这个物理内存供用户态进程访问。但对于操作系统而言能够操作硬件资源只能时操作系统内核来完成。

Linux 内存管理:虚拟内存空间布局_第5张图片
image

你可能感兴趣的:(Linux 内存管理:虚拟内存空间布局)