操作系统——内存管理(面试准备)

虚拟内存

单片机没有操作系统,每次写完代码,都需要借助工具把程序烧录进去,这样程序才能跑起来。
另外,单片机的CPU是直接操作内存的物理地址。

在这里插入图片描述
在这种情况下,想在内存中同时运行两个程序是不可能的,如果第一个程序在2000的位置写入新值,将擦掉第二个程序放在相同位置上的内容,所以同时运行两个程序是根本不通的,会立刻崩溃。

操作系统如何解决

这里的关键问题是这两个程序都引用了绝对物理地址,这是我们最需要避免的。

我们可以把进程使用的地址隔离开来,让操作系统为每个进程分配一套独立的虚拟地址,人人都有,大家只操作自己的地址,互不干涉。
但是有个前提是每个进程都不能访问物理地址,至于虚拟地址最终怎么落到物理内存里,对进程来说是透明的,由操作系统安排。

在这里插入图片描述
操作系统会提供一种机制,将不同的虚拟地址和不同内存的物理地址映射起来。
如果程序要访问虚拟内存的时候,由操作系统转换成不同的物理地址,这样不同的进程运行的时候,写入的是不同的物理地址,这样就不会冲突了。

  • 我们程序使用的内存地址叫做虚拟内存地址
  • 存在硬件空间地址叫做物理内存地址

操作系统引入虚拟内存,进程将持有的虚拟地址通过CPU芯片中的内存管理单元MMU的映射关系,转换变成物理地址,再通过物理地址访问内存。

在这里插入图片描述
操作系统如何管理虚拟地址和物理地址之间的关系呢?

内存分段

程序由若干个逻辑分段组成,如可由代码分段、数据分段。栈段、堆段组成。不同的段有不同的属性,就用分段的形式把这些段分离出来。

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

  • 段选择因子保存在段寄存器里面,段选择因子里面最重要的是段号,用作段表的索引。段表里保存的是这个段的基地址、界限和特权等级。
  • 段内偏移量位于0和段界限之间,如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。

内存分段的缺点:

  • 内存碎片的问题。
  • 内存交换的效率低的问题。

我们来看这样一个例子。我现在手头的这台电脑,有 1GB 的内存。我们先启动一个图形渲染程序,占用了 512MB 的内存,接着启动一个 Chrome 浏览器,占用了 128MB 内存,再启动一个 Python 程序,占用了 256MB 内存。这个时候,我们关掉 Chrome,于是空闲内存还有 1024 - 512 - 256 = 256MB。按理来说,我们有足够的空间再去装载一个 200MB 的程序。但是,这 256MB 的内存空间不是连续的,而是被分成了两段 128MB 的内存。因此,实际情况是,我们的程序没办法加载进来。

内存交换
我们可以把Python程序占用的256MB内存写到硬盘上,然后再从硬盘上读回来到内存里面。不过读回来的时候,我们不再把它加载到原来的位置,而是紧紧跟在那已经被占用了的 512MB 内存后面。这样,我们就有了连续的 256MB 内存空间,就可以去加载一个新的 200MB 的程序。

如果自己安装过Linux操作系统,应该遇到过分配一个swap硬盘分区的问题。这块分出来的磁盘空间,就是专门给Linux操作系统进行内存交换用的。

虚拟内存、分段,再加上内存交换,看起来似乎已经解决了计算机同时装载运行很多个程序的问题。不过,你千万不要大意,这三者的组合仍然会遇到一个性能瓶颈。硬盘的访问速度要比内存慢很多,而每一次内存交换,我们都需要把一大段连续的内存数据写到硬盘上。所以,如果内存交换的时候,交换的是一个很占内存空间的程序,这样整个机器都会显得卡顿。为了解决内存分段的内存碎片和内存交换效率低的问题,就出现了内存分页。

内存分页

分段的好处是能产生连续的内存空间,但是会出现内存碎片和内存交换的空间太大的问题。

要解决这些问题,那么就要想出能少出现一些内存碎片的办法。另外,当需要进行内存交换的时候,让需要交换写入或者从磁盘装载的数据更少一点,这样就可以解决问题了。这个办法,也就是内存分页(Paging)。

分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。这样一个连续并且尺寸固定的内存空间,称为页,Linux下,每一页为4KB。

虚拟地址与物理地址之间通过页表来映射。

页表实际上存储在CPU的内存管理单元(MMU)中,于是CPU可以直接通过MMU,找出要实际访问的物理内存地址。

当进程要访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入系统内核空间分配物理内存,更新进程页表,最后返回用户空间,恢复进程的运行。

分页怎么解决分段的内存碎片、内存交换效率低的问题?

由于内存空间都是预先划分好的,也就不会像分段会产生间隙非常小的内存,采用了分页,释放的内存都是以页为单位释放的,也就不会产生给进程使用的小内存。

如果内存空间不够,操作系统会把其它正在运行的进程中最近没使用的内存页面给释放掉,也就是暂时写作硬盘上,称为换出。一旦需要的时候,再加载进来,称为换入。

一次性写入磁盘的只有少数的一个页或者几个页,不会花太多时间,内存交换的效率也就相对较高。

分页方式使得我们在加载程序的时候,不再需要一次性把程序加载到物理内存中。我们完全可以在进行虚拟内存和物理内存的页之间的映射之后,并不真地把页加载到物理内存里,而是只在程序运行时,需要用到对应虚拟内存页里面的指令和数据时,再加载到物理内存里面去。

分页机制下,虚拟地址分为两部分,页号和页内便宜,页号作为页表的索引,页表包含物理页每页所在物理内存的基地址,这个基地址与页内偏移的组成就形成了物理内存地址。

对于一个内存地址转换,其实也就三个步骤:

  • 把虚拟内存地址,切分成页号和偏移量。
  • 根据页号,从页表里面,查询对应的物理页号。
  • 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。

简单分页

因为操作系统可以同时运行非常多的进程,也就意味着页表会非常庞大。

在32位的环境下,虚拟地址空间有4GB,假设一个页的大小是4KB,那么大概需要100万个页,每个页表项需要4个字节大小存储,那么共需要4MB的内存存储页表。

这4MB大小的页表,看起来也不是很大。但是要知道每个进程都有自己的虚拟地址空间,也就说都有自己的页表。

那么100个进程,就需要400MB的内存来存储页表,这是非常大的内存了,更别说64位的环境了。

多级页表

要解决上面的问题,就需要采用一种叫做多级页表的解决方案。

对于单页表的实现方式,在32位和页大小4KB的环境下,一个进程的页表需要装下100多万个页表项,并且每个页表项占用4字节大小,于是每个页表占用4MB大小的空间。

我们把这个100多万个页表项的单级页表再分页,将页表分为1024个页表(二级页表),每个表(二级页表)中包含1024个页表项,形成二级分页。

为什么多级分页比普通分页更节省内存?

分了二级页表,映射4GB地址空间就需要4KB(一级页表)+4MB(二级页表)的内存,这样占用空间不是更大了吗?

当然如果4GB的虚拟地址全部映射到了物理内存上,二级分页占用空间确实更大了,但是,我们不会为一个进程分配那么多内存。

每个进程都有4GB的虚拟地址空间,而对于大多数程序来说,其使用到的空间远未达到4GB,因为会存在部分对应的页表项都是空的,根本没有分配,对于已分配的页表项,如果存在最近一定时间未访问的页表,在物理内存紧张情况下,操作系统会将页面换出到硬盘,也就是说不会占用物理内存。

如果使用了二级分页,一级页表就可以覆盖整个4GB的虚拟地址空间,如果某一个一级页表的页表项没有被用到,就不需要创建这个页表项对应的二级页表了,即可以在需要时创建二级页表。

程序局部性原理

程序在运行时,对数据的访问往往呈现出局部性特征,即在一段时间内,程序的大部分执行都集中在程序的某一部分,并且这段代码所引用的数据也大多位于相邻的内存区域。

程序局部性原理可以分为两种形式:

  • 时间局部性:在程序执行过程中,如果某个指令或数据已经被访问过,那么在不久之后,该指令或数据很可能再次被访问。例如,在循环体内,同一组指令和数据会被反复执行多次。
  • 空间局部性:某个存储单元被访问过,那么在不久之后,其相邻的存储单元也很可能被访问,例如,数组中的相邻元素通常会被连续访问。

根据程序局部性原理,计算机体系结构中设计了多级缓存、虚拟存储器等技术,操作系统中设计了页面调度、LRU缓存替换算法等机制。

页表缓存TLB

多级页表虽然解决了空间上的问题,但是虚拟地址到物理地址的转换就多了几道转换的工序,这显然就降低了这两个地址转换的速度,也就是带来了时间上的开销。

程序是有局部性的,即在一段时间内,整个程序的执行仅限于程序中某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。

我们利用这一特性,把最常访问的几个页表项存储到访问速度更快的硬件,于是计算机科学家们,就在CPU芯片中,加入了一个专门存放程序最常访问的页表项的Cache,这个Cache就是TLB,通常称为页表缓存,转址旁路缓存、快表等。

在 CPU 芯片里面,封装了内存管理单元(Memory Management Unit)芯片,它用来完成地址转换和 TLB 的访问与交互。有了 TLB 后,那么 CPU 在寻址时,会先查 TLB,如果没找到,才会继续查常规的页表。TLB 的命中率其实是很高的,因为程序最常访问的页就那么几个。

Linux内存管理

在Linux操作系统中,虚拟地址空间的内部又被分为内核空间和用户空间两部分。

在这里插入图片描述
32位系统的内核空间占用1G,位于最高处,剩下的3G是用户空间。

内核空间与用户空间的区别:

  • 进程在用户态时,只能访问用户空间内存;
  • 只有进入内核态时,才可以访问内核空间的内存。

虽然每个进程都有自己的虚拟内存,但是每个虚拟内存中的内核地址,其实关联的都是相同的物理内存。
进程切换到内核态后,就可以很方便地访问内核内存空间。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/375381.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python数据分析案例49——基于机器学习的垃圾邮件分类系统构建(朴素贝叶斯,支持向量机)

案例背景 trec06c是非常经典的邮件分类的数据,还是难能可贵的中文数据集。 这个数据集从一堆txt压缩包里面提取出来整理为excel文件还真不容不易,肯定要做一下文本分类。 虽然现在文本分类基本都是深度学习了,但是传统的机器学习也能做。本案…

【论文速读】《面向深度学习的联合消息传递与自编码器》,无线AI的挑战和解决思路

这篇文章来自华为的渥太华无线先进系统能力中心和无线技术实验室,作者中有大名鼎鼎的童文。 一、自编码架构的全局收发机面临的主要问题 文章对我比较有启发的地方,是提到自编码架构的全局收发机面临的主要问题: 问题一:基于随…

【算法笔记自学】第 9 章 提高篇(3)——数据结构专题(2)

9.1树与二叉树 #include <cstdio>int main() {int n, m;scanf("%d%d", &n, &m);printf(n m 1 ? "Yes" : "No");return 0; } 9.2二叉树的遍历 #include <cstdio> #include <vector> using namespace std;const int…

高精度定位与AI技术的深度融合——未来智慧世界的钥匙

引言在当今迅速发展的科技时代&#xff0c;精确定位和人工智能&#xff08;AI&#xff09;技术正在快速推动各领域的创新与变革。高精度定位结合AI技术所产生的融合效应&#xff0c;正在加速智慧城市、智能驾驶、智能物流以及许多其他领域的实现。这篇文章将详细探讨高精度定位…

科技云报道:产业为根大模型应用为擎,容联云推动企业营销服场景重塑

科技云报道原创。 “没有应用&#xff0c;光有一个基础模型&#xff0c;不管是开源还是闭源&#xff0c;一文不值。”在2024世界人工智能大会&#xff08;WAIC 2024&#xff09;现场&#xff0c;百度创始人、董事长兼首席执行官李彦宏直言。 国产大模型的种类越发丰富&#x…

【爬虫】解析爬取的数据

目录 一、正则表达式1、常用元字符2、量词3、Re模块4、爬取豆瓣电影 二、Xpath1、Xpath解析Ⅰ、节点选择Ⅱ、路径表达式Ⅲ、常用函数 2、爬取豆瓣电影 解析数据&#xff0c;除了前面的BeautifulSoup库&#xff0c;还有正则表达式和Xpath两种方法。 一、正则表达式 正则表达式…

RK3588开发笔记(四):基于定制的RK3588一体主板升级镜像

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140288662 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

Java---SpringBoot详解一

人性本善亦本恶&#xff0c; 喜怒哀乐显真情。 寒冬暖夏皆有道&#xff0c; 善恶终归一念间。 善念慈悲天下广&#xff0c; 恶行自缚梦难安。 人心如镜自省照&#xff0c; 善恶分明照乾坤。 目录 一&#xff0c;入门程序 ①&#xff0c;创建springboot工程&#…

Apache配置与应用(优化apache)

Apache配置解析&#xff08;配置优化&#xff09; Apache链接保持 KeepAlive&#xff1a;决定是否打开连接保持功能&#xff0c;后面接 OFF 表示关闭&#xff0c;接 ON 表示打开 KeepAliveTimeout&#xff1a;表示一次连接多次请求之间的最大间隔时间&#xff0c;即两次请求之间…

秋招Java后端开发冲刺——Mybatis使用总结

一、基本知识 1. 介绍 MyBatis 是 Apache 的一个开源项目&#xff0c;它封装了 JDBC&#xff0c;使开发者只需要关注 SQL 语句本身&#xff0c;而不需要再进行繁琐的 JDBC 编码。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java POJO&#xff08;Plain …

【网络安全科普】网络安全指南请查收

随着社会信息化深入发展&#xff0c;互联网对人类文明进步奖发挥更大的促进作用。但与此同时&#xff0c;互联网领域的问题也日益凸显。网络犯罪、网络监听、网络攻击等是又发生&#xff0c;网络安全与每个人都息息相关&#xff0c;下面&#xff0c;一起来了解网络安全知识吧。…

开放式耳机哪款性价比高?这五款超值精品不容错过

喜欢进行户外运动的小伙伴们&#xff0c;应该都很需要一款既可以匹配运动场景&#xff0c;又兼顾音质体验的无线蓝牙耳机吧。而开放式耳机拥有佩戴舒适牢固&#xff0c;不堵塞耳部&#xff0c;不影响外部声音传入耳部的优点&#xff0c;完全可以成为运动健身人士户外运动的好伴…

『C + ⒈』‘\‘

&#x1f942;在反斜杠(\)有⒉种最常用的功能如下所示&#x1f44b; #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main(void) {int a 10;int b 20;int c 30;if (a 10 &&\b 20 &&\c 30){printf("Your print\n");}else{prin…

Java 多继承与接口

Java 多继承与接口 1、为什么Java不支持多继承&#xff1f;2、使用接口实现多继承2.1 接口的定义与实现 3、接口的优点4、结论 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 多继承是指一个类可以继承多个父类&#xff0c;从而获得多个父类…

Spring Boot Vue 毕设系统讲解 3

目录 项目配置类 项目中配置的相关代码 spring Boot 拦截器相关知识 一、基于URL实现的拦截器&#xff1a; 二、基于注解的拦截器 三、把拦截器添加到配置中&#xff0c;相当于SpringMVC时的配置文件干的事儿&#xff1a; 项目配置类 项目中配置的相关代码 首先定义项目认…

java使用poi-tl模版引擎导出word之if判断条件的使用

文章目录 模版中if语句条件的使用1.数据为False或空集合2.非False或非空集合 模版中if语句条件的使用 如果区块对的值是 null 、false 或者空的集合&#xff0c;位于区块中的所有文档元素将不会显示&#xff0c;这就等同于if语句的条件为 false。语法示例&#xff1a;{{?stat…

Anthropic发布新工具改进大语言模型;商汤科技发布全球首个支持泰文的AI大模型

&#x1f989; AI新闻 &#x1f680; Anthropic发布新工具改进大语言模型 摘要&#xff1a;Anthropic 公司推出多项基于 Claude 3.5 Sonnet 大语言模型的新工具&#xff0c;提升提示词生成和测试能力。新增的“评估”单元帮助开发者自动化生成和微调提示&#xff0c;改进任务…

Kubernetes基于helm部署jenkins

Kubernetes基于helm安装jenkins jenkins支持war包、docker镜像、系统安装包、helm安装等。在Kubernetes上使用Helm安装Jenkins可以简化安装和管理Jenkins的过程。同时借助Kubernetes&#xff0c;jenkins可以实现工作节点的动态调用伸缩&#xff0c;更好的提高资源利用率。通过…

LabVIEW远程实验数据采集系统

随着科学研究的不断发展&#xff0c;实验室对远程数据采集和监控的需求越来越高。传统的数据采集方式往往需要实验人员亲临现场&#xff0c;费时费力&#xff0c;且数据实时性较差。为了解决这些问题&#xff0c;基于LabVIEW开发了一套远程实验数据采集系统&#xff0c;实现对实…

PPTP、L2TP、IPSec、IPS 有什么区别?

随着互联网的发展&#xff0c;保护网络通信的安全越来越重要。PPTP、L2TP、IPSec、IPS是常见的网络安全协议和技术&#xff0c;在保护网络通信安全方面发挥着不同的作用和特点。下面介绍PPTP、L2TP、IPSec、IPS之间的区别。 点对点隧道协议&#xff08;PPTP&#xff09;是一种用…