当前位置: 首页 > news >正文

内存管理问题总结

内存管理

虚拟内存

我们程序所使⽤的内存地址叫做虚拟内存地址Virtual Memory Address

实际存在硬件⾥⾯的空间地址叫物理内存地址Physical Memory Address

操作系统引⼊了虚拟内存,进程持有的虚拟地址会通过 CPU 芯⽚中的内存管理单元(MMU)的映射关

系,来转换变成物理地址,然后再通过物理地址访问内存

1.操作系统是如何管理虚拟地址与物理地址之间的关系?

主要有两种⽅式,分别是内存分段和内存分⻚,分段是⽐较早提出的,我们先来看看内存分段。

程序是由若⼲个逻辑分段组成的,如可由代码分段、数据分段、栈段、堆段组成。不同的段是有不同的属

性的,所以就⽤分段segmentation的形式把这些段分离出来。

image-20240808114128323

2.分段机制下,虚拟地址和物理地址是如何映射的?

分段机制下的虚拟地址由两部分组成,段选择⼦段内偏移量

image-20240808145337974

段选择⼦就保存在段寄存器⾥⾯。段选择⼦⾥⾯最重要的是段号,⽤作段表的索引。段表⾥⾯保存的

是这个段的基地址、段的界限和特权等级等。

虚拟地址中的段内偏移量应该位于 0 和段界限之间,如果段内偏移量是合法的,就将段基地址加上段

内偏移量得到物理内存地址。

知道了虚拟地址是通过段表与物理地址进⾏映射的,分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有⼀个项,在这⼀项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址,

分段的办法很好,解决了程序本身不需要关⼼具体的物理内存地址的问题,但它也有⼀些不⾜之处:

第⼀个就是内存碎⽚的问题。

第⼆个就是内存交换的效率低的问题。

解决外部内存碎⽚的问题就是内存交换。这个内存交换空间,在 Linux 系统⾥,也就是我们常看到的 Swap 空间,这块空间是从硬盘划分出来的,⽤于内存与硬盘的空间交换。

3.分段为什么会导致内存交换效率低的问题?

对于多进程的系统来说,⽤分段的⽅式,内存碎⽚是很容易产⽣的,产⽣了内存碎⽚,那不得不重新

Swap 内存区域,这个过程会产⽣性能瓶颈。因为硬盘的访问速度要⽐内存慢太多了,每⼀次内存交换,我们都需要把⼀⼤段连续的内存数据写到硬盘

上。所以,如果内存交换的时候,交换的是⼀个占内存空间很⼤的程序,这样整个机器都会显得卡顿。

要解决这些问题,那么就要想出能少出现⼀些内存碎⽚的办法。另外,当需要进⾏内存交换的时候,让需

要交换写⼊或者从磁盘装载的数据更少⼀点,这样就可以解决问题了。这个办法,也就是内存分⻚

Paging)。

分⻚是把整个虚拟和物理内存空间切成⼀段段固定尺⼨的⼤⼩。这样⼀个连续并且尺⼨固定的内存空间,

我们叫Page)。在 Linux 下,每⼀⻚的⼤⼩为 4KB 。

虚拟地址与物理地址之间通过⻚表来映射,如下图:

image-20240808114816523

⻚表是存储在内存⾥的,内存管理单元MMU)就做将虚拟内存地址转换成物理地址的⼯作

⽽当进程访问的虚拟地址在⻚表中查不到时,系统会产⽣⼀个缺⻚异常,进⼊系统内核空间分配物理内

存、更新进程⻚表,最后再返回⽤户空间,恢复进程的运⾏。更进⼀步地,分⻚的⽅式使得我们在加载程序的时候,不再需要⼀次性都把程序加载到物理内存中。我们

完全可以在进⾏虚拟内存和物理内存的⻚之间的映射之后,并不真的把⻚加载到物理内存⾥,⽽是只有在

程序运⾏中,需要⽤到对应虚拟内存⻚⾥⾯的指令和数据时,再加载到物理内存⾥⾯去。

4.分⻚是怎么解决分段的内存碎⽚、内存交换效率低的问题?

由于内存空间都是预先划分好的,也就不会像分段会产⽣间隙⾮常⼩的内存,这正是分段会产⽣内存碎⽚

的原因。⽽采⽤了分⻚,那么释放的内存都是以⻚为单位释放的,也就不会产⽣⽆法给进程使⽤的⼩内

存。

如果内存空间不够,操作系统会把其他正在运⾏的进程中的「最近没被使⽤」的内存⻚⾯给释放掉,也就

是暂时写在硬盘上,称为换出Swap Out)。⼀旦需要的时候,再加载进来,称为换⼊Swap In)。所

以,⼀次性写⼊磁盘的也只有少数的⼀个⻚或者⼏个⻚,不会花太多时间,内存交换的效率就相对⽐较

⾼。

image-20240808175944500

更进⼀步地,分⻚的⽅式使得我们在加载程序的时候,不再需要⼀次性都把程序加载到物理内存中。我们

完全可以在进⾏虚拟内存和物理内存的⻚之间的映射之后,并不真的把⻚加载到物理内存⾥,⽽是只有在

程序运⾏中,需要⽤到对应虚拟内存⻚⾥⾯的指令和数据时,再加载到物理内存⾥⾯去。

5.分⻚机制下,虚拟地址和物理地址是如何映射的?

在分⻚机制下,虚拟地址分为两部分,⻚号⻚内偏移。⻚号作为⻚表的索引,⻚表包含物理⻚每⻚所在

物理内存的基地址,这个基地址与⻚内偏移的组合就形成了物理内存地址,⻅下图。

image-20240808180254583

总结⼀下,对于⼀个内存地址转换,其实就是这样三个步骤:

把虚拟内存地址,切分成⻚号和偏移量;

根据⻚号,从⻚表⾥⾯,查询对应的物理⻚号;

直接拿物理⻚号,加上前⾯的偏移量,就得到了物理内存地址

6.简单的分⻚有什么缺陷吗?

有空间上的缺陷。

因为操作系统是可以同时运⾏⾮常多的进程的,那这不就意味着⻚表会⾮常的庞⼤。

在 32 位的环境下,虚拟地址空间共有 4GB,假设⼀个⻚的⼤⼩是 4KB(2^12),那么就需要⼤约 100 万

(2^20) 个⻚,每个「⻚表项」需要 4 个字节⼤⼩来存储,那么整个 4GB 空间的映射就需要有 4MB

的内存来存储⻚表。

这 4MB ⼤⼩的⻚表,看起来也不是很⼤。但是要知道每个进程都是有⾃⼰的虚拟地址空间的,也就说都有

⾃⼰的⻚表。那么, 100 个进程的话,就需要 400MB 的内存来存储⻚表,这是⾮常⼤的内存了,更别说 64 位的环

境了。

要解决上⾯的问题,就需要采⽤⼀种叫作多级⻚表Multi-Level Page Table)的解决⽅案。

多级⻚表虽然解决了空间上的问题,但是虚拟地址到物理地址的转换就多了⼏道转换的⼯序,这显然就降

低了这俩地址转换的速度,也就是带来了时间上的开销。

程序是有局部性的,即在⼀段时间内,整个程序的执⾏仅限于程序中的某⼀部分。相应地,执⾏所访问的

存储空间也局限于某个内存区域。

我们就可以利⽤这⼀特性,把最常访问的⼏个⻚表项存储到访问速度更快的硬件,于是计算机科学家们,

就**在 CPU 芯⽚中,**加⼊了⼀个专⻔存放程序最常访问的⻚表项的 Cache,这个 Cache 就是 TLB

==(Translation Lookaside Buffer) ,==通常称为⻚表缓存、转址旁路缓存、快表等。

image-20240808181645910

在 CPU 芯⽚⾥⾯,封装了内存管理单元(Memory Management Unit)芯⽚,它⽤来完成地址转换和 TLB

的访问与交互。

有了 TLB 后,那么 CPU 在寻址时,会先查 TLB,如果没找到,才会继续查常规的⻚表。

TLB 的命中率其实是很⾼的,因为程序最常访问的⻚就那么⼏个。

7.Intel 处理器的内存管理发展历史。

早期 Intel 的处理器从 80286 开始使⽤的是段式内存管理。但是很快发现,光有段式内存管理⽽没有⻚式

内存管理是不够的,这会使它的 X86 系列会失去市场的竞争⼒。因此,在不久以后的 80386 中就实现了对

⻚式内存管理。也就是说,80386 除了完成并完善从 80286 开始的段式内存管理的同时还实现了⻚式内存

管理。

但是这个 80386 的⻚式内存管理设计时,没有绕开段式内存管理,⽽是建⽴在段式内存管理的基础上,这

就意味着,⻚式内存管理的作⽤是在由段式内存管理所映射⽽成的地址上再加上⼀层地址映射。

由于此时由段式内存管理映射⽽成的地址不再是“物理地址”了,Intel 就称之为“线性地址”(也称虚拟地

址)。于是,段式内存管理先将逻辑地址映射成线性地址,然后再由⻚式内存管理将线性地址映射成物理

地址。

image-20240808182708151

这⾥说明下逻辑地址和线性地址:

程序所使⽤的地址,通常是没被段式内存管理映射的地址,称为逻辑地址

通过段式内存管理映射的地址,称为线性地址,也叫虚拟地址

逻辑地址是「段式内存管理」转换前的地址,线性地址则是「⻚式内存管理」转换前的地址。

8.Linux 采⽤了什么⽅式管理内存?

Linux 内存主要采⽤的是⻚式内存管理,但同时也不可避免地涉及了段机制

这主要是上⾯ Intel 处理器发展历史导致的,因为 Intel X86 CPU ⼀律对程序中使⽤的地址先进⾏段式映

射,然后才能进⾏⻚式映射。既然 CPU 的硬件结构是这样,Linux 内核也只好服从 Intel 的选择。

但是事实上,Linux 内核所采取的办法是使段式映射的过程实际上不起什么作⽤。也就是说,“上有政策,

下有对策”,若惹不起就躲着⾛。

Linux 系统中的每个段都是从 0 地址开始的整个 4GB **虚拟空间(**32 位环境下),也就是所有的段的起始

**地址都是⼀样的。这意味着,**Linux 系统中的代码,包括操作系统本身的代码和应⽤程序代码,所⾯对的

地址空间都是线性地址空间(虚拟地址),这种做法相当于屏蔽了处理器中的逻辑地址概念,段只被⽤于

访问控制和内存保护。

9.Linux 的虚拟地址空间是如何分布的?

在 Linux 操作系统中,虚拟地址空间的内部⼜被分为内核空间和⽤户空间两部分,不同位数的系统,地址

空间的范围也不同。⽐如最常⻅的 32 位和 64 位系统,如下所示:

image-20240808183027250

通过这⾥可以看出:

32 位系统的内核空间占⽤ 1G ,位于最⾼处,剩下的 3G 是⽤户空间;

64 位系统的内核空间和⽤户空间都是 128T ,分别占据整个内存空间的最⾼和最低处,剩下的中

间部分是未定义的

,内核空间与⽤户空间的区别:

进程在⽤户态时,只能访问⽤户空间内存;

只有进⼊内核态后,才可以访问内核空间的内存;虽然每个进程都各⾃有独⽴的虚拟内存,但是每个虚拟内存中的内核地址,其实关联的都是相同的物理内

。这样,进程切换到内核态后,就可以很⽅便地访问内核空间内存。

image-20240808183155678

进⼀步了解虚拟空间的划分情况,⽤户空间和内核空间划分的⽅式是不同的,内核空间的分布情

况就不多说了。

我们看看⽤户空间分布的情况,以 32 位系统为例,我画了⼀张图来表示它们的关系:

image-20240808183239252

⽤户空间内存,从低到⾼分别是 7 种不同的内存段:

程序⽂件段,包括⼆进制可执⾏代码;

已初始化数据段,包括静态常量;

未初始化数据段,包括未初始化的静态变量;

堆段,包括动态分配的内存,从低地址开始向上增⻓;

⽂件映射段,包括动态库、共享内存等,从低地址开始向上增⻓(跟硬件和内核版本有关);

栈段,包括局部变量和函数调⽤的上下⽂等。栈的⼤⼩是固定的,⼀般是 8 MB 。当然系统也提供

了参数,以便我们⾃定义⼤⼩;在这 7 个内存段中,堆和⽂件映射段的内存是动态分配的。⽐如说,使⽤ C 标准库的 malloc() 或者

mmap() ,就可以分别在堆和⽂件映射段动态分配内存。

相关文章:

内存管理问题总结

内存管理 虚拟内存 我们程序所使⽤的内存地址叫做虚拟内存地址(Virtual Memory Address) 实际存在硬件⾥⾯的空间地址叫物理内存地址(Physical Memory Address) 操作系统引⼊了虚拟内存,进程持有的虚拟地址会通过 …...

十七、Intellij IDEA2022.1.1下载、安装、激活

目录 🌻🌻 一、下载二、 安装三、激活 一、下载 官网下载地址 本地直接下载 目前Intellij IDEA的最新版本已经更新到了 2024.1.4,由于最新版本可能存在不稳定的问题,此处选择其他版本进行下载,此处以2022.1.1为例进行下…...

【Material-UI】Button Group 中的 Disabled Elevation 功能

文章目录 一、Button Group 组件概述二、什么是 Elevation?三、为什么需要禁用 Elevation?四、使用 disableElevation 属性五、属性解析1. disableElevation 属性2. variant 属性3. aria-label 属性 六、应用场景1. 表单操作2. 工具栏3. 导航按钮 七、样…...

Java RESTful API 测试:使用 RestAssured

Java RESTful API 测试:使用 RestAssured 简介 在现代软件开发中,RESTful API扮演着至关重要的角色。API的测试同样重要以确保它们按预期工作。Java中的RestAssured库提供了一种简单直观的方式来测试RESTful Web服务。本文将介绍RestAssured的基本概念…...

将nestjs项目迁移到阿里云函数

注意:长耗时,高内存 的应用,定时任务 不适合迁移。 根据模板创建项目 一、模板配置修改 1.node版本修改 由于我的nestjs项目是node18的需要修改 pre-deploy项目: 改成 resources:framework:component: fc3actions:pre-deploy:-…...

边缘计算×AI:绘制未来实时智能的宏伟蓝图

引言:时代的召唤 随着物联网技术的飞速发展,数以亿计的传感器和智能设备正不断涌入我们的生活和工作空间,它们生成的数据量级之大,远非传统的集中式云处理所能高效应对。因此,一种新兴的数据处理模式——边缘计算&…...

实现关系运算符的重载

全局函数的实现法: 成员函数实现法:...

【css】使用CSS绘制奥运五环--巴黎奥运

使用CSS绘制奥运五环 在2024年巴黎奥运会期间,本文来使用 CSS 来画一个奥运五环。奥运五环由五个相互交叠的圆环组成,分别代表五大洲。 奥运五环是相互连接的,因此在视觉上会产生重叠效果,这也是实现五环最有挑战性的部分 HTML结…...

【Python数据处理】MatplotlibNumpyPandas常用API整理

目录 Matplotlib 1. 导入 Matplotlib 并创建图布 2. 实现基础绘图 2.1 折线图 2.2 柱状图 2.3 散点图 2.4 直方图 3. 完善绘图辅助功能 3.1 添加标题和标签 3.2 添加网格线 3.3 添加图例 4. 在一个坐标系下绘制多个图像 5. 在一个图形窗口创建多个子图 5.1 使用 a…...

Nacos是阿里巴巴开源的一款分布式服务注册中心和配置中心

Nacos是阿里巴巴开源的一款分布式服务注册中心和配置中心,旨在帮助开发人员更轻松地构建和管理微服务架构。以下是关于Nacos的详细介绍: 一、概述 Nacos是Dynamic Naming and Configuration Service(动态命名和配置服务)的缩写&a…...

条形码与二维码报表

概述 条形码与二维码:演示条形码与二维码,条形码数据将来自于关联的字段值。支持各种常用的条形码与二维码。 应用场景 如下图所示,简单展示数据 示例说明 数据准备 在数据面板中添加数据集,可选择Json数据集和API服务数据…...

数据采集工具之Flume

本文主要实现数据到datahub的采集过程 1、下载 Index of /dist/flume/1.11.0 datahub插件下载 https://aliyun-datahub.oss-cn-hangzhou.aliyuncs.com/tools/aliyun-flume-datahub-sink-2.0.9.tar.gz 2、安装 $ tar aliyun-flume-datahub-sink-x.x.x.tar.gz $ cd aliyun-…...

【24年最新】AI大模型零基础入门到精通学习资料大全,学完你就是LLM大师!

零基础如何学习大模型 AI 领取方式在文末 为什么要学习大模型? 学习大模型课程的重要性在于它能够极大地促进个人在人工智能领域的专业发展。大模型技术,如自然语言处理和图像识别,正在推动着人工智能的新发展阶段。通过学习大模型课程&am…...

使用RabbitMQ死信交换机实现延迟消息

文章目录 什么是死信交换机?死信交换机实现延迟消息的思路实现过程配置类消费者监听死信队列发送延迟消息 注意事项总结 在开发过程中,我们常常会遇到需要延迟处理某些消息的场景,例如订单的支付超时处理、短信的定时发送等。本文将介绍如何使…...

overleaf上latex表格的使用,latex绘制三线表

三线表需要的包、代码及其示例解释。 一般需要用到的包: \usepackage{tabu} % 表格插入 \usepackage{multirow} % 一般用以设计表格,将所行合并 \usepackage{multicol} % 合并多列 \usepackage{m…...

聚焦光热型太阳光模拟器助力多晶硅均匀加热

晶圆均匀加热技术综述 晶圆均匀加热是半导体制造过程中的关键技术之一,直接影响着晶圆上各种加工工艺的质量和稳定性。晶圆加热的目的在于化学气相沉积、退火、氧化等工艺中,通过对晶圆进行必要的热处理,以促进或优化后续工艺步骤。不均匀的…...

【Android】四大组件(Activity、Service、Broadcast Receiver、Content Provider)、结构目录

文章目录 Android系统架构Android四大组件ActivityServiceBroadcast ReceiverContent Provider 两大视图主要结构目录 Android系统架构 https://blog.csdn.net/xzzteach/article/details/140904613 Android四大组件 Activity 一个 Activity 包含了用户能够看到的界面&#xff0…...

前端开发:创建可拖动的固定位置 `<div>` 和自动隐藏悬浮按钮

在前端开发中&#xff0c;实现一个可拖动的固定位置 <div>&#xff0c;并且根据拖动的状态控制其显示和隐藏&#xff0c;同时在特定条件下显示悬浮按钮&#xff0c;涉及以下技术和原理&#xff1a; 技术细节和实现步骤&#xff1a; 1. HTML 结构&#xff1a; <!DOC…...

Java Bean Validation 注解:@NotEmpty、@NotBlank 和 @NotNull 的区别

1. 概述 Bean Validation 是 Java 提供的一种对 Java Bean 实例的字段或方法参数进行校验的标准机制。它允许开发者使用注解的方式定义验证逻辑&#xff0c;这些注解可以在类、字段或者方法上声明&#xff0c;并且可以被任何实现了 JSR 303/JSR 349 规范的框架&#xff08;如 …...

Java | Leetcode Java题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; public class Solution {public int coinChange(int[] coins, int amount) {int max amount 1;int[] dp new int[amount 1];Arrays.fill(dp, max);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j)…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...