操作系统核心知识点整理--内存篇

news2024/12/22 13:14:49

操作系统核心知识点整理--内存篇

  • 按段对内存进行管理
    • 内存分区
    • 内存分页
    • 为什么需要多级页表
    • TLB解决了多级页表什么样的缺陷?
      • TLB缓存命中率高的原理是什么?
  • 段页结合: 为什么需要虚拟内存?
    • 虚拟地址到物理地址的转换过程
    • 段页式管理下程序如何载入内存?
  • 页面置换
  • 总结
  • 推荐阅读


本文主要面向应用层软件开发人员整理一篇必须了解的操作系统核心知识图谱,每小节参考文章链接都已经在小节末尾给出,如果大家有疑问,可以评论区留言,或者直接去阅读原文。


按段对内存进行管理

为什么程序要按段载入内存?

  • 如果我们直接将程序代码全部放到内存中,这不利于内存的利用和程序的运行,因为,通常程序被编译后都会分为多个段,各个段都有其各自的特点,如: 代码段只读,栈段和堆可以动态扩展。
  • 因此,通常会将程序分段载入内存中来,如果不进行分段载入,如果程序栈空间不足,需要扩展,就需要复制整个程序代码到新分配好的更大的内存空间才可以。

内存分段管理是怎么个玩法 ?

  • 每个进程需要关联一个段表,用于记录当前进程对应程序的各个段信息,如: 段的基址,段的限长,段的特权级等
    在这里插入图片描述
  • 程序分段载入内存,这个过程中需要不断为每个段在内存中寻找空闲分区
  • 同时在对应进程的段表中添加一条表项,记录当前段的存放位置等信息

内存分区

如果我们采用内存分区的方式来对物理内存进行管理,那么此时我们有两种选择:

  • 固定分区
  • 可变分区

显然,我们程序的各个段的大小都是不固定的,因此固定分区可以排除。

如果采用可变分区进行管理,我们需要使用空闲分区表或者空闲分区链表的方式来记录当前内存中各个空闲分区块。

在这里插入图片描述
当接受到一个段内存申请请求时,我们可以采用: 首次适配,最佳适配,最差适配,首次循环适配等算法来进行内存的分配。

但是无论采用何种分配算法,都容易导致内存碎片的产生,随着分配次数的增加,内存碎片越来越多,当某个内存申请请求发起后,发现只有内部内存碎片才能完成内存分配时,这时候就需要进行内存紧缩。

内存紧缩需要花费的时间开销很大,这个过程中cpu无法访问内存,给用户的感觉就是操作系统死机了。


内存分页

想要解决内存分区导致的内存碎片问题,最简单的方法就是采用内存分页,针对每个段的内存请求,系统一页一页的分配给这个短,加入这个段需要3页半的大小的内存,那我就分配给他四整页的内存。

在这里插入图片描述
当我们将段数据打散存放到多个页中时,由于四个物理页的顺序未必是连续的,所以我们需要将分配给段0的页进行编号,这里的编号我们称为虚页号,那么下一个问题就来了,如何根据虚页号定位物理页号呢?

  • 页表: 存放虚页号到物理页号的映射关系

如果对物理内存采用分页管理,那么此时我们程序发出的逻辑地址就由虚页号+页内偏移组成了,通过查询页表将虚页号转换为对应的物理页号,最终计算出物理地址:
在这里插入图片描述

为了实现页表的快速查询,在页表中虚页号不直接提供,而是作为页表数组的索引隐含其中,但是这就意味着页表必须要连续的内存存储。


为什么需要多级页表

以Linux 0.11中每页4K进行计算,对于32位操作系统而言,其发出的32位的虚拟地址最多可以定位到1M的页数。

那么就意味着页表需要维护1M个虚拟页号和物理页号的映射关系,那么页表占据的内存就会很大。

解决这个问题有两种思路:

  • 由于大部分逻辑地址用不到,因此我们只在页表中存储用到的虚页号,如果采取这个办法,那么我们就无法通过虚页号快速定位到页表中的具体表项了,可能需要多出几千次额外内存访问。–> 页表必须是顺序排列的,没用到的虚页号也必须保留,这样才能够以一次访存的代价定位到具体的表项。
  • 多级页表:

我们目前遇到的困境是: 页表项太多,并且要求页表中的页表项是连续存放的,不管当前虚页号是否用到。

解决思路: 借鉴书目录与小节的思想,将页表项分散存储到多个页表中,各个页表内的页表项是连续存储的,然后通过页目录管理多个页表,确保多个页表之间的顺序性,从而就保证了页表项整体顺序性。

在这里插入图片描述
引入了多级页表中,我们的页目录中的页目录项都是连续存放的,每个页目录项指向一个页表,这保证了多个页表之间的顺序性。

当前进程只需要载入自己需要的页目录项指向的页表到内存即可,至于自己用不到的页目录项,则无需载入其对应的页表到内存,这样可以大大节约内存,并且访问次数也只需要两次即可。

同时只有一级页表才总是需要缓存在内存中的,对于二级页表而言,也只会在需要用到的时候才申请内存进行创建,这对于一个普通程序而言,在虚拟地址空间大部分都是未分配的情况下,会节约大量的内存。


TLB解决了多级页表什么样的缺陷?

多级页表的缺陷: 相比于单级页表,层级每增加一级,都需要多出一个访问内存的开销。

但是为了保证页表项的整体连续性,并且还要减少页表对内存的浪费,就必须采用多级页表的形式,但是多级页表时间上的不足,就需要通过缓存来弥补了,也就是TLB。

在这里插入图片描述
通过CPU内部的TLB寄存器,来缓存最近使用到的页,并且因为TLB采用的是相联存储设计,硬件可以直接通过虚页号定位到缓存中某个表项,然后直接得到对应的物理页号,从而计算出物理地址。


TLB缓存命中率高的原理是什么?

程序访问存在局部性原理,通常在某个时间段内,只会频繁某几个页面号,那么因为TLB缓存了对应的页面号,所以命中率就很高。


段页结合: 为什么需要虚拟内存?

首先,我们的程序需要按段载入内存,如果按照上面最终敲定的内存分页方案,那么我们程序的各个段都会被打散存放到多个不相邻或者相邻的物理页上,当然还需要给每个物理页编排一个虚拟页号,用于还原段,这个过程中使用页表完成虚页号到物理页号的映射关系:
在这里插入图片描述
这种方式对于内存的管理而言非常友好,不会造成内存碎片,但是站在程序的视角来看,段内的内存是不连续的。

我们开发者更希望看到的进程内存图是各个段在内存上连续存放:
在这里插入图片描述
问题: 能否站在程序员的视角看来,程序分段存放在内存上的模样是连续的,但是站在物理内存视角看来,却是分页管理的呢?

在这里插入图片描述

为了实现呈现给上层用户段连续存放的内存图模型,操作系统提供了对应虚拟内存来解决这个问题。

有了虚拟内存的之后,用户写的程序首先在虚拟内存中划分出对应的空间来存放,但是实际程序载入内存时,却会根据先前划分的虚拟地址空间,分别打散存储到对应多个物理页上。

当用户想要访问内存时,也只需要面向虚拟内存操作即可,用户发出的地址都是虚拟地址,但是操作系统通过将虚拟地址映射到物理地址后,用户就可以正常读取和设置物理内存中的数据了,对于用户而言操作虚拟内存和物理内存无区别。

段页结合的关键在于:用户能够看到的虚拟内存中,段是连续存放在内存中,而实际的物理内存依然采用分页管理,所以对应各个程序段依然会被打散存储到各个物理页中,这个过程对用户无感。


虚拟地址到物理地址的转换过程

引入段页结合内存管理后,用户程序发出的虚拟地址重定向到物理地址的过程也发生了很大变化:

  • 首先,用户发出的虚拟地址由段号+段内偏移组成,通过查询段表,获得段基址,拼接段内偏移,得到虚拟地址
  • 虚拟地址,经过MMU计算,得到虚拟页号,然后查询对应的页表,得到真实的物理页号
  • 通过真实的物理页号+页内偏移,得到最终物理地址

具体通过MMU完成虚拟地址到物理地址转换过程,可以参考本文


段页式管理下程序如何载入内存?

  • 首先在虚拟内存中通过分区适配算法,找到一块空闲分区来存放程序中的段,这里实际是在对应的段表中新增一条表项,记录当前段在虚拟内存中的段基址和段限长等信息。
  • 将虚拟内存中分配的段空间打散,按照对应的分页机制,映射到若干物理页上,由对应的页表保存虚页号到物理页号的映射关系。
  • 配合磁盘读写,将程序分段读入到对应的物理页上。

在这里插入图片描述
当用户需要访存时,首先通过段号,查询段表,得到段基址; 然后拼接段内偏移地址得到虚拟地址,再通过对应的分页机制,解析出虚拟地址对应到页表中哪一个表项,然后得到对应的物理页号,通过物理页号就可以轻松计算出物理页号的基址,加上页内偏移地址,最终计算出实际的物理地址。


页面置换

地址映射过程中,如果访问页表访问对应的页面不在内存,或者还未建立映射关系,则会发生缺页中断。

当发生缺页中断时,如果当前内存中没有空闲页面,操作系统就必须在内存中选择一个页面移出内存,以便为即将调入的页面让出空间。

具体选择淘汰哪一个页的规则叫做页面置换算法,常见的有:

  • 先进先出(FIFO)
  • 最近最久未使用(LRU)
  • Clock算法,LRU的近似实现

操作系统内存换出—15

包括还需要限制每个进程所能分配到的页面数,即当前进程的工作集,每次要置换页面时,只会在当前进程的工作集中选择并进行淘汰。


总结

  • 谈谈内存分段管理和分页管理的联系

我们编写的程序编译后都是分段的,因此程序载入内存的过程也应该是分段载入,但是分段对内存进行管理,会产生大量内存碎片,并且内存紧缩的过程也非常耗时。

所以采用分页管理后,内存空间利用率会提供,不会产生外部碎片,只会有少量页内碎片。

但是分页管理的缺点在于不方便按照模块实现信息的共享和保护,而采用分段的方式则非常容易实现。

所以,最终的一个解决方案是程序按段载入内存,然后被打散存储到各个物理页上,通过页表完成虚拟页号到物理页号的映射关系。

  • 聊聊多级页表的作用吧

在Linux 0.11环境下,每个物理页大小为4k,那么在32位系统环境下,其发出的32位虚拟地址最多可以定位到1M的页数。那么就意味着我们的页表需要连续存放1M个页表项,页表会占据很多内存。

引入多级页表可以解决页表占据内存过大的问题,通过引入页目录层,我们的进程只需要加载那些使用到的页目录项指向的页表到内存即可,其他页目录项指向的页表则无需载入内存,从而可以大大减少页表占据的内存。

并且也只需要将页目录缓存在内存中,其中的页目录项指向的页表,也可以得到第一次使用到时,才申请内存进行创建。

  • tlb有什么作用呢

多级页表可以减少页表占据内存过大的问题,但是也导致一次访存请求,会额外多出n次多级页表查询请求,为了解决这个问题,就引入了缓存来弥补多级页表在时间上不足。

tlb作为CPU内部的相联存储寄存器,用来缓存最近访问过的虚拟页号和物理页号的映射关系,利用的是程序执行的局部性原理,可以有很高的命中率。

  • 什么是虚拟内存,为什么需要虚拟内存,虚拟内存有什么好处?

什么是虚拟内存: 虚拟内存为每个进程提供了一个一致性,连续的,私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉。

为什么需要虚拟内存: 为了给用户呈现出一个按段加载,并且各个段在内存中连续存放的内存视图,方便用户编写程序。

虚拟内存好处:

  • 给用户呈现一个连续的一致性内存视图,使程序编写难度降低。
  • 把内存范围扩展到了硬盘: 加载程序时,可以只加载需要使用到的段,并且程序运行过程中,也可以将不常访问的段换出到磁盘存储。有的操作系统还可以在内存不足的情况下,将某一进程内存全部放入硬盘空间中,并在切换到进程时再从硬盘读取。
  • 对于共享库的实现非常方便,只需要将不同进程对应的虚拟地址空间中划分出一块地址空间映射到同一个物理内存区域即可。

推荐阅读

CSAPP,操作系统导论,哈工大操作系统课程

虚拟内存的那点事儿

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NCNN Conv量化详解1

1. NCNN的Conv量化计算流程 正常的fp32计算中,一个Conv的计算流程如下: 在NCNN Conv进行Int8计算时,计算流程如下: NCNN首先将输入(bottom_blob)和权重(weight_blob)量化成INT8,在INT8下计算卷积,然后反量化到fp32,再和未量化的bias相加,得到输出(top_blob) 输入和…

学了一年Java的我,想转嵌入式了

秋名山码民的主页 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 🙏作者水平有限,如发现错误,还请私信或者评论区留言! 目录前言为啥我想去转行?如果我现在选择转硬件,我…

【华为OD机试模拟题】用 C++ 实现 - 相同字符连续出现的最大次数(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

计算机网络——问答2023自用

1、高速缓冲存储器Cache的作用? 这种局部存储器介于CPU与主存储器DRAM之间,一般由高速SRAM构成,容量小但速度快,引入它是为了减小或消除CPU与内存之间的速度差异对系统性能带来的影响 (Cache可以保存CPU刚用过或循环使…

【react storybook】从零搭建react脚手架,并使用storybook发布组件库到npm,并生成可视化UI文档

storybook成品展示开发准备开发组件写MDX文档发布文档发布组件成品展示 可视化UI文档页面: 可视化UI文档地址: https://guozia007.gitee.io/storybook-ui/?path/docs/mdx-button--default-story组件库地址: https://www.npmjs.com/pac…

Vmware虚拟机无法联通主机解决方法二

昨天在遇到了VMware 虚拟机无法联通主机,导致我在CentOS-7 搭建的伪Hadoop3 服务,无法访问管理平台,使用将网络编辑器修改为“桥接”模式解决。今天在学习HBase 时,昨天的问题又重新了,我通过SSH 工具MobaXterm 都无法…

《第一行代码》 第八章:应用手机多媒体

一&#xff0c;使用通知 第一步&#xff0c;创建项目&#xff0c;书写布局 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"android:layout_width"match_parent"android:layout_he…

【数据结构趣味多】Map和Set

1.概念及场景 Map和set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索的效率与其具体的实例化子类有关。 在此之前&#xff0c;我还接触过直接查询O(N)和二分查询O(logN)&#xff0c;这两个查询有很多不足之出&#xff0c;直接查询的速率太低&#xff0c;而二分查…

如何压缩RAR格式文件?

RAR是我们日常生活工作中经常用到的压缩文件格式之一&#xff0c;那么RAR文件如何压缩呢&#xff1f; 不管压缩哪种格式的压缩文件&#xff0c;我们都需要用到压缩软件。针对RAR格式&#xff0c;我们可以选择最常见的WinRAR&#xff0c;当然如果有同样适用于RAR格式的压缩软件…

不写注释就是垃圾

最近Linux6.2出来了增加了很多新的东西&#xff0c;有看点的是&#xff0c;Linux确实要可以在Apple M1上面运行了&#xff0c;这应该是一个很大的新闻&#xff0c;如果有这么稳定的硬件支持&#xff0c;那对于Linux来说相当于又打下了一大片的江山。其中关于Linux6.2的特性罗列…

cesium: 显示闪烁的点(004)

第004个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置闪烁的点。主要是介绍entity>point 相关的属性设置 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共107行)相关API参考:专栏目标示例效果 配…

一个阿里P6的说不会接口自动化测试,他不会是自己评的吧...

序 近期和一个阿里的测试工程师交流了一波&#xff0c;他竟然说我不会接口自动化测试&#xff0c;我当场就不服了我说你P6自己评级的吧&#xff0c;今天就带大家好好盘一盘接口自动化&#xff0c;本着以和大家交流如何实现高效的接口测试为出发点&#xff0c;本文包含了我在接…

27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组(双指针遍历)

目录[27. 移除元素-力扣](https://leetcode.cn/problems/remove-element/description/?languageTagsc)[26. 删除有序数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)[88. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-…

Synchronized与锁升级

文章目录先从阿里及其他大厂面试题说起本章路线总纲Synchronized的性能变化synchronized锁种类及升级步骤JIT编译器对锁的优化小总结先从阿里及其他大厂面试题说起 谈谈你对synchronized的理解 synchronized锁升级你聊聊 本章路线总纲 说明&#xff1a; synchronized锁&a…

Java-排序链表问题

Java-排序链表问题题目题解方法&#xff1a;自顶向下归并排序算法题目 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 示例 2&#xff1a; 示例 3&#xff1a; 提示&#xff1a; *链表中节点的数目在范围 [0, 5 * 104]…

Linux 练习一(常用命令的练习)

文章目录一、Linux 用户管理及文件操作第一段练习记录&#xff1a;主要对用户进行删除添加设置密码等操作第二段练习记录&#xff1a;主要包括权限设置和查找命令第三段练习记录&#xff1a;关于文件的命令练习第四段练习记录&#xff1a;查找命令及查看内存命令的使用二、Linu…

ClickHouse高可用集群分片-副本实操(四)

目录 一、ClickHouse高可用之ReplicatedMergeTree引擎 二、 ClickHouse高可用架构准备-环境说明和ZK搭建 三、高可用集群架构-ClickHouse副本配置实操 四、ClickHouse高可用集群架构分片 4.1 ClickHouse高可用架构之两分片实操 4.2 ClickHouse高可用架构之两分片建表实操 一…

AXI协议

AXI 的英文全称是 Advanced eXtensible Interface&#xff0c;即高级可扩展接口&#xff0c;它是 ARM 公司所提出的AMBA&#xff08;Advanced Microcontroller Bus Architecture&#xff09;协议的一部分。AXI 协议就是描述了主设备和从设备之间的数据传输方式&#xff0c;在该…

理解redis的数据结构

redis为什么快&#xff1f; 首先可以想到内存读写数据本来就快&#xff0c;然后IO复用快&#xff0c;单线程没有静态消耗和锁机制快。 还有就是数据结构的设计快。这是因为&#xff0c;键值对是按一定的数据结构来组织的&#xff0c;操作键值对最终就是对数据结构进行增删改查操…

【CSS】CSS 层叠样式表 ② ( CSS 引入方式 - 内嵌样式 )

文章目录一、CSS 引入方式 - 内嵌样式1、内嵌样式语法2、内嵌样式示例3、内嵌样式完整代码示例4、内嵌样式运行效果一、CSS 引入方式 - 内嵌样式 1、内嵌样式语法 CSS 内嵌样式 , 一般将 CSS 样式写在 HTML 的 head 标签中 ; CSS 内嵌样式 语法如下 : <head><style …