为什么要有虚拟内存?

操作系统是通过内存分段和内存分页的方式管理虚拟内存地址和物理内存地址之间的关系

内存分段

程序是由若干个逻辑分段组成的,代码分段、数据分段、栈段、堆段组成,不同的段有不同的属性,所以就用分段的形式分离开。

分段机制下的虚拟内存由两部分组成,段选择因子和段内偏移量。段选择因子里面有段号,段号是段表的索引,段表是一个表,里面保存的有该段的基地址、段的界限和特权等级。段内偏移量应该位于 0 和段界限之间,如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。

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

每个段的长度是不一样的,而且每个段内部都是从0开始编制的。 每个段内部是连续分配内存,但是段和段之间是离散分配的。

 分段的方式解决了程序员不需要关心具体的物理地址内存的问题,但是有一些不足之处:

  • 存在内存碎片(外部碎片),可以通过内存交换的方式解决
  • 内存交换的效率低,把内存写到硬盘上面太慢了

 内存分页

内存分页是为了减少内存碎片、加快内存交换的方式。

分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。每个页的大小是4k。 虚拟地址与物理地址之间通过页表来映射。

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

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

分页的话,页与页之间是紧密排列的,所以不会存在外部碎片。内存分页机制分配内存的最小单位是一页,即使程序不足一页大小,最少只能分配一个页,所以页内会出现内存浪费,所以针对内存分页机制会存在内部内存碎片的现象。

如果内存分页不够,操作系统会把其他正在运行的进程中的最近没有被使用的内存页给换出到硬盘上面。 一旦需要的话,再从磁盘上面换入到内存里面。由于一次性换入或者换出的只有少数几个页,所以不用花费太多的时间。

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

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

虚拟地址分为两部分,页号和页内偏移,页号是页表的索引,页表中存储的是虚拟页号和物理页号,物理页号可以查找物理内存的基地址,基地址划伤页内偏移量就能找到真实的物理地址。

简单的分页有什么问题? 

32位的环境下,每个进程的虚拟地址空间都有4GB,一个页的大小是4kb,那么就会存在4GB / 4KB = 100万个页,每个页中有的页表项 需要4个字节大小来存储,那么整个4GB的映射需要4MB的内存来存储页表。 如果有100个进程的话,需要400M来存储,耗费比较大。

多级页表是什么?

每个进程的100万个页共用的一个页表 ,该页表占用的4MB空间。 4M空间来说有些大了,我们把这100万个页表项的单级页再分页,将一级页表再分为1024个二级页表,每个二级页表中包含1024个页表项。

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

如果把4GB的虚拟地址全部都映射到了物理内存上的话,确实二级分页占用的空间更大了,但是,我们不会为一个进程分配太多的内存。 对于每个进程来说,其使用的空间没有达到4GB,因为会存在部分对应的页表项都是空的,对于已经分配的页表项,如果最近一段时间没有被使用,在物理内存紧张的情况下,也是会被换出的。

那么为什么不分级的页表就做不到这样节约内存呢?

页表一定要覆盖全部的虚拟地址空间,不分级的页表需要100万个页表项来映射,而分级的页表只需要1024个页表项。

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

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

相关文章

JVM理论(七)性能监控与调优

概述 性能优化的步骤 性能监控:就是通过以非强行或入侵方式收集或查看应用程序运行状态,包括如下问题 GC频繁CPU过载过高OOM内存泄漏死锁程序响应时间较长性能分析:通常在系统测试环境或者开发环境进行分析 通过查看程序日志以及GC日志,或者运用命令行工…

《零基础入门学习Python》第070讲:GUI的终极选择:Tkinter7

上节课我们介绍了Text组件的Indexs 索引和 Marks 标记,它们主要是用于定位,Marks 可以看做是特殊的 Indexs,但是它们又不是完全相同的,比如在默认情况下,你在Marks指定的位置中插入数据,Marks 的位置会自动…

yaml语法详解

#kv #对空格的严格要求十分高 #注入到我们的配置类中 #普通的keyvalue name: qinjiang#对象 student:name: qingjiangage: 3#行内写法 student1: {name: qinjiang,age: 3}#数组 pets:- cat- dog- pigpet: [cat,dog,pig]yaml可以给实体类赋值 person:name: kuangshenage: 19happ…

ERROR 1064 - You have an error in your SQL syntax;

ERROR 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near (/, 少个逗号吧,以前开始写SQL,特别是修改SQL的时候容易出现这样错误。 而且自己也知道在附近…

【深度学习】日常笔记15

训练集和测试集并不来⾃同⼀个分布。这就是所谓的分布偏移。 真实⻛险是从真实分布中抽取的所有数据的总体损失的预期,然⽽,这个数据总体通常是⽆法获得的。计算真实风险公式如下: 为概率密度函数 经验⻛险是训练数据的平均损失,⽤…

【MySQL主从复制】

目录 一、MySQL Replication 1.概述 2.优点 二、MySQL复制类型 1.异步复制(Asynchronous repication) 2.全同步复制(Fully synchronous replication) 3.半同步复制(Semisynchronous replication) 三…

ava版知识付费平台免费搭建 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台

提供私有化部署,免费售后,专业技术指导,支持PC、APP、H5、小程序多终端同步,支持二次开发定制,源码交付。 Java版知识付费-轻松拥有知识付费平台 多种直播形式,全面满足直播场景需求 公开课、小班课、独…

Rust ESP32C3开发

Rust ESP32C3开发 系统开发逐步使用Rust语言,在嵌入式领域Rust也逐步完善,本着学习Rust和ESP32的目的,搭建了ESP32C3的环境,过程中遇到了不少问题,予以记录。 ESP-IDF开发ESP32 这一部分可跳过,是使用C开…

python测试开发面试常考题:装饰器

目录 简介 应用 第一类对象 装饰器 描述器descriptor 资料获取方法 简介 Python 装饰器是一个可调用的(函数、方法或类),它获得一个函数对象 func_in 作为输入,并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。 装饰器模式通常用…

【数据结构】实验十一:图

实验十一 图 一、实验目的与要求 1)掌握图的存储表示与操作实现。 2)掌握图的连通性及其应用。 二、 实验内容 1.用邻接表存储一个图形结构,并计算每个顶点的度。 2. 采用深度和广度优先搜索算法,遍历上述这张图,…

vue 实现拖拽效果

实现方式:使用自定义指令可以实现多个面板拖拽互不影响 1.自定义指令 js directives: {// 拖拽drag(el) {el.onmousedown function (e) {let x e.pageX - el.offsetLeftlet y e.pageY - el.offsetTopdocument.onmousemove function (e) {el.style.left e.pag…

【期末课程设计】学生成绩管理系统

因其独特,因其始终如一 文章目录 一、学生成绩管理系统介绍 二、学生成绩管理系统设计思路 三、源代码 1. test.c 2. Student Management System.c 3.Stu_System.c 4.Teacher.c 5.Student Management System.h 前言: 学生成绩管理系统含教师…

什么是Maven,Maven的概述及基本使用

MAVEN 一、Maven简介1.1、Maven概述1.2、Maven仓库1.3项目获取jar包过程 二、Maven使用2.1Maven安装配置2.1.1配置环境变量2.1.2配置本地仓库2.1.3配置阿里云私服 2.2Maven基本使用2.2.1Maven常用指令2.2.2Maven生命周期 总结 一、Maven简介 Apache Maven是一个项目管理和构建…

STM32 I2C OVR 错误

一、问题 STM32 I2C 用作从机时,开启如下中断并启用 callback 回调函数。 每一次复位后,从机都可以正常触发地址匹配中断ADDR,之后在该中断的回调函数中启用接收中断去收取数据时,却无法进入RXNE中断,而是触发了 OVR …

<C语言> 动态内存管理

1.动态内存函数 为什么存在动态内存分配? int main(){int num 10; //向栈空间申请4个字节int arr[10]; //向栈空间申请了40个字节return 0; }上述的开辟空间的方式有两个特点: 空间开辟大小是固定的。数组在申明的时候,必须指定数组的…

自然语言处理NLP介绍——NLP简介

目录 内容先进性说明内容大纲概要云服务器的使用 内容先进性说明 内容大纲概要 云服务器的使用

githack的安装步骤+一次错误体验

一.githack的安装步骤 1.要在Kali Linux上安装GitHack工具,您可以按照以下步骤操作: 打开终端并使用以下命令克隆GitHack存储库: git clone https://github.com/lijiejie/GitHack.git2.进入GitHack目录: cd GitHack3.安装依赖项…

一种分解多种信号模式非线性线性调频的方法研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Elasticsearch

文章目录 分布式搜索引擎elasticsearch介绍elasticsearch作用ELK技术栈elasticsearch和lucene 倒排索引正向索引倒排索引正向和倒排比较 es的一些概念文档和字段索引和映射mysql与elasticsearch elasticsearch安装部署单点es部署kibana安装IK分词器扩展词词典停用词典 索引库操…

Go语言基础语法八万字详解,对小白友好

基本语法——变量var 变量的使用 什么是变量 变量是为存储特定类型的值而提供给内存位置的名称。在go中声明变量有多种语法。 所以变量的本质就是一小块内存,用于存储数据,在程序运行过程中数值可以改变 声明变量 var名称类型是声明单个变量的语法…