内存学习(一):物理地址空间内存概述

简介: 内存学习(一):物理地址空间内存概述


内存管理框架

整个内存的框架图如下所示:

图片

可以看出整个内存框架自上而下分为三层:用户、内核、硬件。当有了这个三层的架构意识后,我们自上而下来认识一下内存。

一、用户

在这个一层,如果你曾经写过关于嵌入式或者c语言的代码你就会认识malloc,即使是高级语言的内存申请,本质上也是对malloc的封装以及优化。

当然还记得老师说的malloc和free一定要尽量对称好使用。

这个malloc是谁给咱们的呢?

malloc()和free()是glibc库内存分配器ptmalloc提供的接口,ptmalloc使用系统调用brk或mmap向内核以页为单位申请内存,然后划分成小内存块分配给应用程序。

用户空间的内存分配器,除了glibc库的ptmalloc,还有谷歌公司的tcmalloc和FreeBSD的jemalloc。(但是大多数编译器都是集成了glibc,所以我们常用的就是malloc)

二、内核

当我们在前一节我们假如使用了malloc,那么通过ptmalloc(glibc)–>brk/mmap–>进入到了内核。

在用户空间动态申请内存用的函数是 malloc(),那么在内核空间中如何申请内存呢?一般我们会用到 kmalloc()、kzalloc()、vmalloc() 等

内核里面又能做什么?

图片

1-内核基本功能

1、接口

图片

虚拟内存管理负责从进程的虚拟地址空间分配虚拟页

  • sys_brk用来扩大或收缩堆,
  • sys_mmap用来在内存映射区域分配虚拟页,
  • sys_munmap用来释放虚拟页。

内核使用延迟分配物理内存的策略,进程第一次访问虚拟页的时候,触发页错误异常,页错误异常处理程序从页分配器申请物理页,在进程的页表中把虚拟页映射到物理页。(为啥这样干的目的,就是因为想通过这样的方式来省内存。)

2、内存分配器

图片

页分配器负责分配物理页,当前使用的页分配器是伙伴分配器。

内核空间提供了把页划分成小内存块分配的块分配器,提供分配内存的**接口kmalloc()**和释放内存的接口kfree(),支持3种块分配器:

  • SLAB分配器、
  • SLUB分配器
  • SLOB分配器。

在内核初始化的过程中,页分配器还没准备好,需要使用临时的引导内存分配器分配内存。 因为在内核初始化的时候,这个内存分配机制还没建立好。这个部分东西有一篇博客很好,但是略微抽象,后续可看。

2-内核扩展功能

图片

1、vmalloc

不连续页分配器提供了分配内存的接口vmalloc和释放内存的接口vfree,在内存碎片化的时候,申请连续物理页的成功率很低,可以申请不连续的物理页,映射到连续的虚拟页,即虚拟地址连续而物理地址不连续。

这里你肯定好奇这个vmalloc和malloc还有kmalloc有什么区别?

kmalloc和vmalloc是分配内核的内存,malloc分配的是用户空间的内存。

2、per_cpu

每处理器内存分配器用来为每处理器变量分配内存。(per_cpu)

3、CMA

连续内存分配器(Contiguous Memory Allocator, CMA)用来给驱动程序预留一段连续的内存当驱动程序不用的时候,可以给进程使用当驱动程序需要使用的时候,把进程占用的内存通过回收或迁移的方式让出来,给驱动程序使用

4、内存控制组

内存控制组用来控制进程占用的内存资源。

5、碎片化内存整理

当内存碎片化的时候,找不到连续的物理页,内存碎片整理(“memory compaction”的意译,直译为“内存紧缩”)通过迁移的方式得到连续的物理页。

6、内存回收-页回收

在内存不足的时候,页回收负责回收物理页,对于没有后备存储设备支持的匿名页,把数据换出到交换区,然后释放物理页

对于有后备存储设备支持的文件页,把数据写回存储设备,然后释放物理页

如果页回收失败,使用最后一招:内存耗尽杀手(OOM killer, Out-of-Memory killer),选择进程杀掉。

三、硬件

图片

1-MMU

处理器包含一个称为内存管理单元(Memory Management Unit, MMU)的部件,负责把虚拟地址转换成物理地址。

2-TLB

内存管理单元包含一个称为页表缓存(Translation Lookaside Buffer, TLB)的部件,保存最近使用过的页表映射,避免每次把虚拟地址转换成物理地址都需要查询内存中的页表。

3-缓存

为了解决处理器的执行速度和内存的访问速度不匹配的问题在处理器和内存之间增加了缓存

缓存通常分为一级缓存和二级缓存,为了支持并行地取指令和取数据一级缓存分为数据缓存和指令缓存

目录
相关文章
|
3月前
|
存储 开发框架 .NET
"揭秘.NET内存奥秘:从CIL深处窥探值类型与引用类型的生死较量,一场关于速度与空间的激情大戏!"
【8月更文挑战第16天】在.NET框架中,通过CIL(公共中间语言)可以深入了解值类型与引用类型的内存分配机制。值类型如`int`和`double`直接在方法调用堆栈上分配,访问迅速,生命周期随栈帧销毁而结束。引用类型如`string`在托管堆上分配,堆栈上仅存储引用,CLR负责垃圾回收,确保高效且自动化的内存管理。
56 6
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
21天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
194 2
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
53 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
1月前
|
C++
析构造函数就是为了释放内存,就是在局部指针消失前释放内存,拷贝构造函数就是以构造函数为模块,在堆里面新开一块,同一个变量在堆里面的地址
本文讨论了C++中构造函数和析构函数的作用,特别是它们在管理动态内存分配和释放中的重要性,以及如何正确地实现拷贝构造函数以避免内存泄漏。
37 2
|
1月前
|
存储 安全 NoSQL
driftingblues9 - 溢出ASLR(内存地址随机化机制)
driftingblues9 - 溢出ASLR(内存地址随机化机制)
36 1
|
2月前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
130 5
|
3月前
|
存储 JavaScript 前端开发
学习JavaScript 内存机制
【8月更文挑战第23天】学习JavaScript 内存机制
34 3
|
3月前
|
算法 安全 UED
探索操作系统的内核空间:虚拟内存管理
【7月更文挑战第50天】 在现代操作系统中,虚拟内存管理是核心功能之一,它允许操作系统高效地使用物理内存,并为应用程序提供独立的地址空间。本文将深入探讨操作系统虚拟内存管理的机制,包括分页、分段以及内存交换等关键技术,并分析它们如何共同作用以实现内存的有效管理和保护。通过理解这些原理,读者可以更好地把握操作系统的内部工作原理及其对应用程序性能的影响。