内存管理 | 进程地址空间

1.进程地址空间的理解

在 前文 分享的fork创建子进程的系统调用中,一个变量接收了两个不同的返回值!通过推测也知道,那个地址绝不是真是的地址(物理地址),而是一个虚拟的地址!

在操作系统中,进程所用的地址是独立的一套虚拟地址,系统通过一套机制,将虚拟地址映射到真正存储数据的物理地址!其实在单片机或是早期的计算机都是直接操作物理地址地址的,但是如果一台计算机有两个不同的进程,访问同一个物理地址,那么就会造成程序崩溃,虚拟地址的内存管理机制就避免了这种情况,让多进程运行变成了可能!

在这里插入图片描述

  • 我们程序所使用的内存地址叫做虚拟内存地址(Virtual Memory Address)
  • 实际存在硬件里面的空间地址叫物理内存地址(Physical Memory Address)

操作系统中通过CPU中的内存管理单元(MMU 来将虚拟地址映射到物理地址当中,然后再通过物理地址访问内存

在这里插入图片描述

如何理解

虚拟化技术是操作系统的惯用手法,为进程运行分配很短(毫秒级)的时间片,让人感绝自己的程序一直运行;操作系统运行虚拟地址空间(进程地址空间),为进程营造一种,计算机的所有内存都被自己(每一个进程)占有!在32位的机器上,4G的空间都是每个进程独占的,进程之间感受不到彼此的存在!

在这里插入图片描述

举一个生活的例子:

一个富豪有十亿美金,有两个私生子,分别叫张三,李四,每个私生子之间都不知道有彼此的存在!张三喜欢学习,李四喜欢跑步!

一天富豪就分别对两个儿子说:张三啊,你好好学习,争取拿个诺贝尔奖,我以后十个亿的家产都是你的;同样的话又对李四说,李四啊,你好好跑步,争取拿个奥运冠军,我以后十个亿的家产都是你的。

我们能看出来,这个富豪,是个画家!从例子类比到计算当中:

富豪:操作系统 ; 私生子:一个一个进程

富豪画的:进程地址空间(注意名词:饼) ; 生活中真正的饼:物理空间

张三或李四之间感受不到彼此的存在,如果他们向富豪要100万,没问题!但是给十个亿,那显然富豪给不了!

对比到操作系统也是一样,一个进程不可能独占4G,4G有1G的内核空间,还有系统的那么多其他进程,但是系统能通过这种方式很好的管理(先描述,再组织)!在Linux中进程地址空间/虚拟地址空间:就是内核管理的数据结构(mm_struct结构体)!

struct task_struct {struct mm_struct *mm, *active_mm;
}
struct mm_struct 
{...unsigned long total_vm, locked_vm, shared_vm, exec_vm;unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;unsigned long start_code, end_code, start_data, end_data;unsigned long start_brk, brk, start_stack;unsigned long arg_start, arg_end, env_start, env_end;...
}

这里我们就可以理解fork一个变量就收两个返回值

子进程的创建会以父进程作为模板,进行拷贝,对于一些代码和只读的数据父子进程共享,对于需要修改的数据,系统使用写时拷贝的技术,将需要修改的数据拷贝一份然后再对其进行修改。

这就解释了,为什么一个虚拟地址或变量有两个不同的值!因为同一个虚拟地址,不同的进程映射到了不同的物理地址!通过虚拟内存 + 页表映射的方式和一些写时拷贝的技术保证了进程的独立性!

在这里插入图片描述

2.将虚拟地址转换为物理地址

这一段内容我几乎是搬运小林哥的博客!

操作系统如何将虚拟地址转化成物理地址

将虚拟地址转化成物理地址主要有这两种方式:内存分段内存分页,Linux系统中采用的是内存分页的方式将虚拟内存映射到物理内存当中,但两种都是通过起始地址 + 偏移量的方式转换

内存分段

在这里插入图片描述

虚拟地址分为段选择因子和段内偏移量,在段选择因子当中可以通过段号来找到段表中的段基地址,从而获取物理地址的起始地址,再通过偏移量,找到对应的物理地址!

内存分段的不足:

  • 第一个就是内存碎片的问题。
  • 第二个就是内存交换的效率低的问题。

内存碎片主要分为,内部内存碎片和外部内存碎片

外部内存碎片

在这里插入图片描述

内部内存碎片

在计算机中,会通过内存对齐的方式,来提高计算机读取的效率,比如:实际的数据是5字节,但是根据内存对齐分配了8字节,剩下的3个字节就是内部碎片!

再堆的管理当中堆内存碎片是管理的重点,malloc在一定的场景下上会有许多的内存碎片问题!

内存交换

内存分段管理可以做到段根据实际需求分配内存,所以有多少需求就分配多大的段,所以不会出现内部内存碎片。但是由于每个段的长度不固定,所以多个段未必能恰好使用所有的内存空间,会产生了多个不连续的小物理内存,导致新的程序无法被装载,所以会出现外部内存碎片的问题。

可以通过内存交换的方式解决外部碎片问题:

将一些程序换出(挂起),在重新组织换入;所谓的换出就是将程序换出到swap分区中,到但是swap是磁盘会有效率的消耗。

内存分页

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

在这里插入图片描述

页表是存储在内存里的,内存管理单元 (MMU)就做将虚拟内存地址转换成物理地址的工作。

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

虚拟内存如何通过分页转换成物理内存

在这里插入图片描述

步骤:

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

简单的分页的缺陷

在 32 位的环境下,虚拟地址空间共有 4GB,假设一个页的大小是 4KB(2^12),那么就需要大约 100 万 (2^20) 个页,每个「页表项」需要 4 个字节大小来存储,那么整个 4GB 空间的映射就需要有 4MB 的内存来存储页表。

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

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

多级页表

我们把这个 100 多万个「页表项」的单级页表再分页,将页表(一级页表)分为 1024 个页表(二级页表),每个表(二级页表)中包含 1024 个「页表项」,形成二级分页。如下图所示:

在这里插入图片描述

如果使用了二级分页,一级页表就可以覆盖整个 4GB 虚拟地址空间,但如果某个一级页表的页表项没有被用到,也就不需要创建这个页表项对应的二级页表了,即可以在需要时才创建二级页表。做个简单的计算,假设只有 20% 的一级页表项被用到了,那么页表占用的内存空间就只有 4KB(一级页表) + 20% * 4MB(二级页表)= 0.804MB,这对比单级页表的 4MB 是不是一个巨大的节约!

程序是按需加载的,在32位机器上不然小小的4G内存,怎么能装的下几十G的游戏!

3.进程地址空间的设计

虚拟地址在什么时候就有呢,在程序加载到内存之前有没有地址

可以通过一些反汇编的工具来,查看,在编译好了的程序,就存在了虚拟地址!

objdump -afh 可执行程序

结果:编译器和系统之间用的是同一套进程地址空间的设计方案,这样编译器和操作系统才能配合工作。

在这里插入图片描述

CPU在执行指令的时候用的是什么样的地址

虚拟地址

在这里插入图片描述

4.进程地址空间的好处

1.防止非法访问

当非法的访问或映射是,操作系统都或识别并终止你的进程,从而保护了物理内存。进程地址空间和页表都是由操作系统创建并维护的,也就意味着使用地址空间和页表进行映射都在操作系统的监管之下,如果你是非法的,操作系统就会终止你的进程,这也说明了进程的崩溃,就是操作系统杀死了你的进程!

2.内存和进程管理模块解耦

有了进程地址空间和页表映射的存在,我们的数据(数据+代码)可以映射到任意的物理内存的位置!这就说明了,内存管理模块和进程管理模块可以做到没有关联的关系,做到了解耦合!

所有,在C、C++语言上使用malloc函数和new的时候是在虚拟内存空间上申请的,或也可是说是在进程地址空间上申请的。虽然在地址空间上申请了空间,但是在物理内存甚至一个字节都不给你!

因为我们申请的空间有是都并不会直接到,当你真正的对物理内存进程访问的时候,才会执行相关的内存管理算法,帮你申请内存。

这是使用到了延迟分配的策略,来提高整机的效率,这是由操作系统来自动完成的,对用户的继承来说,完全是零感知的。

3.内存分布有序化

物理内存可以加载到任何一个地方,这样几乎所有的代码和数据都是乱序的!而乱序的东西是不便于管理的!通过页表的存进可以将虚拟内存和物理内存一一映射,站在进程的角度上所有的内存都是有序的,便于管理。

请的。虽然在地址空间上申请了空间,但是在物理内存甚至一个字节都不给你!

因为我们申请的空间有是都并不会直接到,当你真正的对物理内存进程访问的时候,才会执行相关的内存管理算法,帮你申请内存。

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

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

相关文章

基于SpringBoot的记账系统项目

点击以下链接获取源码:https://download.csdn.net/download/qq_64505944/88822660?spm1001.2014.3001.5503 Java项目-8 开发工具:IDEA/Eclipse,MySQL,Tomcat 项目框架:SpringBoot,layui 功能:可以按照类型和时间查询&#xff0c…

融资项目——获取树形结构的数据

如下图所示,下列数据是一个树形结构数据,行业中包含若干子节点。表的设计如下图,设置了一个id为1的虚拟根节点。(本树形结构带虚拟根节点共三层) 实现逻辑: 延时展示方法,先展现第二层的信息&a…

年-月-日的输入方法

大家对于输入的函数一定有所认识&#xff0c;比如c中位于 #include <iostream> 中的 cin 函数&#xff0c;这个函数输入单个十分好用&#xff0c;但是对于年月日这种较为复杂的就行不通了&#xff0c;就只能输入最前面的一个 那怎么输入像这样的年月日呢 答案就是用 scan…

清理神器CleanMyMac X 空间透镜——可视化您的磁盘空间 空间透镜有什么用

不久前&#xff0c;CleanMyMac X 发布了一个新功能&#xff1a; 空间透镜 相信有非常多的小伙伴和小编一样&#xff0c; 对这个功能一脸问号 这啥玩意儿&#xff1f;&#xff1f;&#xff1f; 今天就让我们深入了解一下&#xff0c; CleanMyMac X 的空间透镜功能。 - 更好…

基于SSM的网络在线考试系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的网络在线考试系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring …

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View 0.论文摘要 多视图聚合有望克服多目标检测和跟踪中的遮挡和漏检挑战。多视图检测和3D对象检测中的最新方法通过将所有视图投影到地平面并在鸟瞰视图&#xff08;BEV&#xff09;中执…

第五篇【传奇开心果系列】vant开发移动应用示例:深度解读高度可定制

传奇开心果博文系列 系列博文目录Vant 开发移动应用示例系列 博文目录前言一、Vant高度可定制的重要作用二、样式定制介绍和示例代码三、组件定制介绍和示例代码四、组件库定制介绍和示例代码五、主题定制介绍和示例代码六、语言环境定制介绍和示例代码七、资源加载定制介绍和示…

猫头虎分享已解决Bug || 备份失败(Backup Failures):BackupFailureException, DataBackupError ❌

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

数据结构(C语言)代码实现(八)——顺序栈实现数值转换行编辑程序括号分配汉诺塔

目录 参考资料 顺序栈的实现 头文件SqStack.h&#xff08;顺序栈函数声明&#xff09; 源文件SqStack.cpp&#xff08;顺序栈函数实现&#xff09; 顺序栈的三个应用 数值转换 行编辑程序 顺序栈的实现测试 栈与递归的实现&#xff08;以汉诺塔为例&#xff09; 参考资…

传输层协议 ——— TCP协议

TCP协议 TCP协议谈谈可靠性为什么网络中会存在不可靠&#xff1f;TCP协议格式TCP如何将报头与有效载荷进行分离&#xff1f;序号与确认序号 确认应答机制&#xff08;ACK&#xff09;超时重传机制连接管理机制三次握手四次挥手 流量控制滑动窗口拥塞控制延迟应答捎带应答面向字…

闭区间上连续函数的性质【高数笔记】

1. 分几个性质 2. 每个性质的注意事项是什么 3. 每个性质适用什么类型的题型 4. 注意最值定理和正弦函数的不同 5. 做题步骤是什么

Lua: 一门轻量级、高效的脚本语言

Lua: 一门轻量级、高效的脚本语言 在当今软件开发的领域中&#xff0c;寻找一门既灵活又高效的脚本语言&#xff0c;一直是开发者们追求的目标。Lua作为一门小巧、高效、可嵌入的脚本语言&#xff0c;已经成为了众多开发者的首选之一。无论是游戏开发、嵌入式系统、Web 开发还是…

npm 上传一个自己的应用(2) 创建一个JavaScript函数 并发布到NPM

上文 npm 上传一个自己的应用(1) 搭建一个项目环境 带着大家创建了一个项目环境 我们打开 看json的配置 我们入口是一个叫 index.js 的文件 那么 我们就要把它创建出来 之后 我们的方法也就要写在这里面 和 json同一个目录 创建 index.js 我们这里 写个简单的求和操作 index…

30岁还一事无成,怎么办?

前些日子&#xff0c;知乎有一个话题&#xff0c;特别火。 原话是&#xff1a;30岁&#xff0c;如果你还没当上管理层&#xff0c;或者在某个领域取得成就&#xff0c;那你一辈子基本也就这样了。 这句话一出&#xff0c;戳中了许多人的软肋&#xff0c;一时间群情哗然。 理由是…

(全网最全)微型计算机原理与接口技术第六版课后习题答案-周荷琴,冯焕清-第9章串行通信和可编程 接口芯片8251A-中国科学技术大学出版社

含有“AI:”开头的题目的答案是问chat的&#xff0c;看个乐就行&#xff0c;不一定正确 1。串行通信与并行通信的主要区别是什么&#xff1f;各有什么优缺点? 2。在串行通信中&#xff0c;什么叫单工、半双工、全双工工作方式&#xff1f; 3。什么叫同步工作方式&#xff1f;…

金融信贷风控评分卡模型

评分卡模型概念 评分模型是根据借款人的历史数据&#xff0c;选取不同维度的数据类型&#xff0c;通过计算而得出的对借款人信用情况打分的模型。不同等级的信用分数代表了借款人信用情况的好坏&#xff0c;以此来分析借款人按时还款的可能性。 评分卡模型分类 A卡&#xff…

使用QZipWriter来压缩文件

Qt 自带的压缩QZipWriter和解压QZipReader详解~含Demo-CSDN博客 示例代码1&#xff1a; 压缩一个文件&#xff1a; #include "qzipwriter_p.h" #include "qfileinfo.h" #include <QDebug> int main(int argc, char *argv[]) {QApplication a(argc…

(超详细)10-YOLOV5改进-替换CIou为Wise-IoU

yolov5中box_iou其默认用的是CIoU&#xff0c;其中代码还带有GIoU&#xff0c;DIoU&#xff0c;文件路径&#xff1a;utils/metrics.py&#xff0c;函数名为&#xff1a;bbox_iou 将下面代码放到metrics.py文件里面&#xff0c;原来的bbox_iou函数删掉 class WIoU_Scale: mon…

ARM:AI 的翅膀,还能飞多久?

ARM&#xff08;ARM.O&#xff09;于北京时间 2024 年 2 月 8 日上午的美股盘后发布了 2024 年第三财年报告&#xff08;截止 2023 年 12 月&#xff09;&#xff0c;要点如下&#xff1a; 1、整体业绩&#xff1a;收入再创新高。ARM 在 2024 财年第三季度&#xff08;即 23Q4…

IT行业有哪些证书含金量高呢?

目录 引言&#xff1a; 一、 计算机网络类证书 二、 数据库管理类证书 三、 安全与信息技术管理类证书 四、 编程与开发类证书 五、 数据科学与人工智能类证书 六、结论&#xff1a; 悟已往之不谏&#xff0c;知来者犹可追 …