操作系统--内存管理

一、虚拟内存的提出

单片机

  • 没有操作系统
  • 只能运行一个程序
  • 每次都要借助工具把代码烧录进去(后面的程序会把之前的覆盖)

单片机的 CPU 是直接操作内存的「物理地址」

现在的问题是

  1. 有操作系统
  2. 需要同时运行多个程序(把进程所使用的地址「隔离」开来)
  3. 每个进程最好都不能直接访问物理地址(后面的程序就不会把之前的覆盖)

解决思路:让操作系统为每个进程分配独立的一套「虚拟地址」,然后操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来。

虚拟内存地址Virtual Memory Address):程序所使用的内存地址

物理内存地址Physical Memory Address):实际存在硬件里面的空间地址

内存管理单元(MMU):包含虚拟地址和物理地址的映射关系,在CPU芯片中


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

1.内存分段

内存分段是根据程序的逻辑角度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段,同时是一块连续的空间。

虚拟地址

  • 段选择因子(在段寄存器中):段号、标志位
  • 段内偏移量

映射关系

  • 段表:段基地址、段界限、特权级

物理地址

  • 段起始地址(段基地址)
  • 段界限
  • 偏移量

分段机制:分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有一个项,在这一项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址。

缺点

  • 存在外部内存碎片的问题,解决办法就是内存交换
  • 内存交换效率低,因为每一次内存交换,都需要把一大段连续的内存数据写到硬盘上,而硬盘的访问速度要比内存慢太多。若交换的是一个占内存空间很大的程序,整个机器都会显得卡顿

内存碎片

  • 内部内存碎片:没有根据实际需求分配内存,比如很小的程序分配很大的内存
  • 外部内存碎片:由于每个段的长度不固定,所以多个段未必能恰好使用所有的内存空间,会产生了多个不连续的小物理内存,导致新的程序无法被装载

内存交换

每个进程都有自己的虚拟空间,而物理内存只有一个,所以当启用了大量的进程,物理内存必然会很紧张,于是操作系统会通过内存交换技术,把不常使用的内存暂时存放到硬盘(换出),在需要的时候再装载回物理内存(换入)。

2.内存分页

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

分页是怎么解决分段的「外部内存碎片和内存交换效率低」的问题?

内存分页由于内存空间都是预先划分好的,也就不会像内存分段一样,在段与段之间会产生间隙非常小的内存,这正是分段会产生外部内存碎片的原因。而采用了分页,页与页之间是紧密排列的,所以不会有外部碎片。

但是,因为内存分页机制分配内存的最小单位是一页,即使程序不足一页大小,我们最少只能分配一个页,所以页内会出现内存浪费,所以针对内存分页机制会有内部内存碎片的现象。

如果内存空间不够,操作系统会把其他正在运行的进程中的「最近没被使用」的内存页面给释放掉,也就是暂时写在硬盘上,称为换出Swap Out)。一旦需要的时候,再加载进来,称为换入Swap In)。所以,一次性写入磁盘的也只有少数的一个页或者几个页,不会花太多时间,内存交换的效率就相对比较高。

虚拟地址

  • 虚拟页号:页表的索引
  • 页内偏移

映射关系

  • 页表(在内存中):虚拟页号、物理页号
  • 内存管理单元(MMU) :做将虚拟内存地址转换成物理地址的工作

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

物理地址

  • 物理页号:每页所在物理内存的基地址
  • 偏移量

分页机制

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

缺点

  • 存在内部内存碎片的问题
  • 页表会占用非常大的内存空间,解决方法就是多级页表

3.多级页表

首先,要知道一级页表必须覆盖整个虚拟地址空间,不然虚拟地址在页表中找不到对应的页表项,计算机系统就不能工作了。

如果不使用二级分页,一级页表的占用内存会非常庞大。

但如果使用了二级分页,根据计算机系统的局部性原理假如某个一级页表的页表项没有被用到,也就不需要创建这个页表项对应的二级页表了,即可以在需要时才创建二级页表

对于64位的系统,使用四级页表目录

  • 全局页目录项 PGD(Page Global Directory);
  • 上层页目录项 PUD(Page Upper Directory);
  • 中间页目录项 PMD(Page Middle Directory);
  • 页表项 PTE(Page Table Entry);

缺点

  • 降低了虚拟、物理地址转换速度,带来了时间上的开销,解决办法就是页表缓存TLB

4.页表缓存TLB

页表缓存(TLB)专门存放程序最常访问的页表项的CPU Cache

内存管理单元(MMU:完成地址转换和 TLB 的访问与交互

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


三、段页式内存管理

段页式内存管理 = 内存分段 + 内存分页

实现方式:先分段,每段再分页

地址结构:段号、段内页号、页内位移

数据结构:每一个程序一张段表,每个段又建立一张页表,段表中的地址是页表的起始地址,而页表中的地址则为某页的物理页号

段页式地址变换

  • 第一次访问段表,得到页表起始地址;
  • 第二次访问页表,得到物理页号;
  • 第三次将物理页号与页内位移组合,得到物理地址。


 四、Linux内存管理

1.Intel 处理器

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

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

80386 的页式内存管理设计建立在段式内存管理的基础上,这就意味着,页式内存管理的作用是在由段式内存管理所映射而成的地址上再加上一层地址映射。

此时由段式内存管理映射而成的地址不再是“物理地址”了,Intel 就称之为“线性地址”(也称虚拟地址)。于是,段式内存管理先将逻辑地址映射成线性地址,然后再由页式内存管理将线性地址映射成物理地址。

2.Linux内存管理

Linux 系统主要采用了分页管理,但是由于 Intel 处理器的发展史,Linux 系统无法避免分段管理。于是 Linux 就把所有段的基地址设为 0,也就意味着所有程序的地址空间都是线性地址空间(虚拟地址),相当于屏蔽了 CPU 逻辑地址的概念,所以段只被用于访问控制和内存保护。

3.Linux虚拟地址空间分布

虚拟地址空间

  • 内核空间:只有进入内核态后,才可以访问内核空间的内存
  • 用户空间:进程在用户态时,只能访问用户空间内存
  • 不同位数的系统,地址空间的范围也不同

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

3.1.内核空间分布

省略

3.2.用户空间分布

以 32 位系统为例:

用户空间内存分布,从低到高分别是 6 种不同的内存段:

  • 代码段,包括二进制可执行代码;
  • 数据段,包括已初始化的静态常量和全局变量;
  • BSS 段,包括未初始化的静态变量和全局变量;
  • 堆段,包括动态分配的内存,从低地址开始向上增长;
  • 文件映射段,包括动态库、共享内存等,从低地址开始向上增长;
  • 栈段,包括局部变量和函数调用的上下文等。栈的大小是固定的,一般是 8 MB。当然系统也提供了参数,以便我们自定义大小;
  • 保留区(灰色部分),之所以要有保留区这是因为在大多数的系统里,我们认为比较小数值的地址不是一个合法地址,例如,我们通常在 C 的代码里会将无效的指针赋值为 NULL。因此,这里会出现一段不可访问的内存保留区,防止程序因为出现 bug,导致读或写了一些小内存地址的数据,而使得程序跑飞。

五、补充

虚拟内存有什么作用?

  • 可以使得进程对运行内存超过物理内存大小,因为程序运行符合局部性原理,CPU 访问内存会有很明显的重复访问的倾向性,对于那些没有被经常使用到的内存,我们可以把它换出到物理内存之外,比如硬盘上的 swap 区域。
  • 由于每个进程都有自己的页表,所以每个进程的虚拟内存空间就是相互独立的。进程也没有办法访问其他进程的页表,所以这些页表是私有的,这就解决了多进程之间地址冲突的问题
  • 页表里的页表项中除了物理地址之外,还有一些标记属性的比特,比如控制一个页的读写权限,标记该页是否存在等。在内存访问方面,操作系统提供了更好的安全性

六、参考

小林 coding

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

车载以太网——DDS篇

摘要: DDS为信息交换和应用程序集成创建了一个简单而强大的体系结构。 01、什么是DDS DDS是一系列标准,它指定了分布式应用程序可用于交换实时数据的API、协议和安全机制。应用程序所使用的软件应用程序编程接口(API)是基于一个…

“超人练习法”系列09:耶克斯–多德森定律

01 你现有水平和学习风格 搞明白自己是个大事,搞不明白就糊涂一辈子。 首先,要弄清楚自己现在是个啥水平,有啥技能可以拿出来的,然后再定个目标,知道自己想往哪方面努力。 你擅长的学习方式是啥呢?是那种…

架构的未来:微前端与微服务的融合

目录 前言 微服务架构简介 微前端架构简介 微前端与微服务的融合 1. 共享服务 2. 基于事件的通信 3. 统一的身份和认证 4. 交付管道的集成 示例:使用微服务和微前端的电子商务平台 微服务架构 微前端架构 融合微服务和微前端 总结 作者简介…

智慧康养项目:智能技术与产品提升老年人生活品质

智慧康养项目需要集成的一些独特的技术和产品,其中包括: 智能健康监测设备:我们开发了一款能够实时监测老年人身体状况的智能健康监测设备,包括血压、血糖、心率等指标。该设备通过数据分析处理,能够提供个性化的健康…

【微信小程序独立开发 3】个人资料页面编写

这一节完成用户个人信息昵称的填写和获取 上节编写完成后的页面如下所示: 首先进行用户昵称编辑功能的编写,铲屎官昵称采用了navigator标签,当点击昵称时会自动跳转到昵称编辑页面。 首先输入昵称编辑界面的导航栏名称 {"usingCompone…

On the Robustness of Backdoor-based Watermarkingin Deep Neural Networks

关于深度神经网络中基于后门的数字水印的鲁棒性 ABSTRACT 在过去的几年中,数字水印算法已被引入,用于保护深度学习模型免受未经授权的重新分发。我们调查了最新深度神经网络水印方案的鲁棒性和可靠性。我们专注于基于后门的水印技术,并提出了…

CHS_04.2.1.5+进程通信

CHS_04.2.1.5进程通信 进程通信为什么进程通信需要操作系统支持?共享存储消息传递消息传递(间接通信方式)进程通信——管道通信 知识回顾与重要考点 进程通信 在这个小节中 我们会学习进程间通信的几种方式 分别是共享 存储 消息传递 还要管道…

软件测试|Selenium 元素不可交互异常ElementNotInteractableException问题分析与解决

简介 在使用 Selenium 进行 Web 自动化测试时,我们可能会遇到各种异常情况。其中之一就是 ElementNotInteractableException 异常,这通常意味着在尝试与页面元素交互时出现了问题。本文将详细介绍这个异常的原因、可能的解决方法,并提供示例…

Git仓库管理笔记

问题: hint: the same ref. If you want to integrate the remote changes, use Done 解决: 解决方法: 1、先使用pull命令: git pull --rebase origin master 2、再使用push命令: git push -u origin master

银行网络安全实战对抗体系建设实践

文章目录 前言一、传统攻防演练面临的瓶颈与挑战(一)银行成熟的网络安全防护体系1、缺少金融特色的演练场景设计2、资产测绘手段与防护体系不适配3、效果评价体系缺少演练过程维度相关指标 二、实战对抗体系建设的创新实践(一)建立…

【RTOS】快速体验FreeRTOS所有常用API(4)队列

目录 四、队列2.1 概念2.2 创建队列2.3 写队列2.4 读队列2.5 队列集(可跳过) 四、队列 该部分在上份代码基础上修改得来,代码下载链接: https://wwzr.lanzout.com/iBNAS1l75bvc 密码:7xy2 该代码尽量做到最简,不添加多…

解决Qt的release构建下无法进入断点调试的问题

在工作的时候遇到了第三方库只提供release版本的库的情况,我需要在这基础上封装一层自家库,在调试的时候遇到如下问题,但是在Qt环境下,release的库只能在进行release构建和调试。 卡在了一直进不了断点的情况。提示内容如下&#…

【IPC通信--共享内存】

进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如…

Linux操作系统——文件详解

1.文件理解预备知识 首先,当我们在磁盘创建一个空文件时,这个文件会不会占据磁盘空间呢? 答案是当然会占据磁盘空间了,因为文件是空的,仅仅指的是它的内容是空的,但是该文件要有对应的文件名,…

【数据库和表的管理】

数据库和表的管理 一、实验目的 了解MySQL数据库的逻辑结构和物理结构的特点。学会使用SQL语句创建、选择、删除数据库。学会使用SQL语句创建、修改、删除表。学会使用SQL语句对表进行插入、修改和删除数据操作。了解MySQL的常用数据类型。 二、实验内容SQL语句创建、选择、删…

玩转硬件之MP3的破解

MP3播放器是一种能播放音乐文件的播放器,主要由存储器(存储卡)、显示器(LCD显示屏)、中央处理器MCU(微控制器)或解码DSP(数字信号处理器) 等组成。 其中微控制器是播放器…

k8s存储卷之动态

动态pv需要两个组件 1、卷插件,k8s本身支持的动态pv创建不包含NFS,需要声明和安装一个外部插件 Provisioner 存储分配器,动态创建pv,然后根据pvc的请求自动绑定和使用 2、StorageClass,用来定义pv的属性&#xff0c…

金蝶云星空单据转换插件-选单

文章目录 金蝶云星空单据转换插件-选单 金蝶云星空单据转换插件-选单 选单使用标识报错 应该使用实体属性

LeetCode 每日一题 Day 44 || 哑节点去重

82. 删除排序链表中的重复元素 II 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 示例 1: 输入:head [1,2,3,3,4,4,5] 输出:[1,2,5] 示例 2&#x…

内存泄漏问题

内存泄漏是一种常见的问题,它可能导致系统内存不断增加,最终耗尽可用内存。解决内存泄漏问题通常需要进行调试和分析。下面是一些可能有助于解决内存泄漏问题的步骤: 1. 监控内存使用情况: a. 使用 malloc 记录日志:…