当前位置: 首页 > news >正文

【进程概念④】:进程地址空间(虚拟内存与物理内存)

【进程概念④】:进程地址空间(虚拟内存与物理内存)

  • 一.进程地址空间
  • 二.分页与虚拟地址
    • ①.what
    • ②.how
    • ③.why
  • 三.页表细节
    • ①.标志位
    • ②.缺页中断
  • 四.总结意义

一.进程地址空间

你觉得我们代码中写的数据都在哪存储着呢?
在内存里存着!确实是在内存里存储着,那你知道数据存在内存的哪里呢?
你以前肯定听过栈,堆,静态区等等的。都是在"内存"上划分的。
在这里插入图片描述
比如局部变量是在栈上开辟的,动态申请的空间是在堆区申请的,全局变量是在全局区(这里又分成初始化数据和未初始化数据)代码都是存在代码段的。
对于栈呢,它是向下增长,也就是向地址减少的地方增长的;对于堆呢,它是向上增长,也就是向地址增长的方向增长的。
所以在我们没有学习进程地址空间时,我们对于内存的印象就是如上图所示。而学习进程地址空间后,你就会发现其实这个并不是真正的"内存"。

理解进程地址空间,我们先理解一下下面这个问题:
【问题】我们知道fork()创建进程时会返回两个值,为什么同一个变量可以接受两不同的值呢?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{pid_t id = fork();if(id < 0){perror("fork");return 0;}else if(id == 0){ //child子进程g_val=100;//将全局变量改成100;printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);}else{ //parent父进程printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(1);return 0;
}

在这里插入图片描述
我们在全局定义一个变量g_val.并初始化为0.
然后利用fork()函数创建两个进程,一个为子进程,一个为父进程,子进程先执行,在子进程中将全局变量修改成g_val修改成100.并打印它的值和地址。在父进程中修改全局变量的值,打印它的值和地址。最后结果显示,子进程和父进程中的全局变量值并不一样,而地址确实一样的,这是为什么呢?

我们可以猜想:
1.变量内容不相同,父子进程中输入的变量肯定不是同一个变量。
2.但是父子进程中,变量的地址却又相同,这说明这个地址肯定不是物理地址,因为物理地址只能一对一,不存在一对多的情况。

其实这里的地址是虚拟地址,在Linux中,我们用c/C++语言所看到的地址都是虚拟地址,都不是物理地址,物理地址用户是看不到的。

二.分页与虚拟地址

其实呢进程并不是直接与物理内存进行交互的,中间还存在着一个叫做进程地址空间的对象。进程地址空间其实就是虚拟内存,而物理内存才是真正的内存,除了进程地址空间外,中间还存在一个叫页表的对象,它是用来将虚拟地址转换映射成物理地址的。页表中其实有很多标识位,比如权限位和判断位等等。最主要还是它可以将虚拟地址映射到物理地址上去,页表的左边存的都是虚拟地址,页表的右边则是存着物理地址。这就形成了映射。当进程访问内存时,先访问的是虚拟内存,然后才是根据页表映射转换到物理内存。
在这里插入图片描述
当使用fork()创建子进程时,子进程也需要进程地址空间,而子进程的进程地址空间是继承父进程的,也就是直接从父进程那拷贝过来的。
子进程的页表其实也是从父进程那拷贝过来的,所以父子进程默认情况下,数据和代码指向都是一样的,也就印证了父子代码共享,数据一般也是共享的,除非发生写实拷贝。
在这里插入图片描述
好的,我们现在再转回到问题上去:为什么fork()返回的两个值可以存在同一个变量里?为什么父子进程的变量值不相同,但地址却相同呢?

首先我们要确定的是,他们这里面发生了写入数据导致发生写实拷贝了。fork()返回返回值时是不是写入?改变全局变量的值是不是写入?
那么写时拷贝发生了什么呢?
写时拷贝,父子进程先写入的就会将要访问的数据拷贝一份,重新开辟内存创建变量。所以关键在于重新开辟了一块空间了。
这时子进程的物理地址就不再指向父进程原来的变量位置,而是指向一块新开辟的空间了。但是这个写时拷贝的过程,并不影响进程虚拟地址。
所以我们就可以知道为什么父子进程中同一个变量值不同了,是因为变量的物理内存不同,它们的地址却相同,是因为写时拷贝不影响虚拟内存。
在这里插入图片描述

①.what

什么是进程地址空间呢?
在这里插入图片描述
什么是32位机器呢?就是它有32个总线。每一根地址总线只有0,1表示。那么可以表示的范围就是0–2^32种了。而这就是该机器下所能表示的内存范围,至于地址空间是什么,就是地址总线排列组合形成的地址范围,能访问的最大范围,也就是一段数据(地址)的范围。

②.how

如何理解地址空间上的区域划分呢?区域又是如何进行划分的呢?
在这里插入图片描述
我们可以假设有一块连续空间,被小胖和小芳两个人共同使用,但是小胖总是喜欢跑到小芳的位置上吃零食,睡觉,小芳这能忍吗?这当然不能忍了。所以小芳就提出划分区域,定出一个三八线出来,不给小胖逾越。那么你想一想应该如何帮助小芳进行区域的划分呢?
我们可以直接定义一个桌面区域结构体,它里面包含着四个变量,小胖的起始位置和小胖的终点位置,小芳的起始位置和小芳的终点位置。这里通过这个结构体对象,我们就可以对该区域进行划分,小芳想要公平公正一些就各自一人一般的区间,谁也不能逾越。

所以结构体对象就可以这样定义:
struct desk_area  justic{ 1,50,51,100 };

所以对于每一个进程来说,除了要有PCB外,还需要进程地址空间。
在进程创建时,操作系统处理创建一个PCB对象给进程,还要创建一个进程地址空间对象给进程。并且操作系统还要对这个地址空间进行管理,至于如何管理呢?先描述,再组织!
在这里插入图片描述

操作系统会像上面一样首先会对进程地址空间进行描述,将空间区域的划分边界变量确定下来。操作系统不是直接在PCB里创建进程地址空间对象,而是在PCB里存储一个指向进程地址空间的指针,然后再利用数据结构进行管理。

1.其实所谓的进程地址空间,本质上就是一个描述进程可视范围的大小,就是进程可以看到内存的范围。
2.地址空间里会存在区域的划分,划分的手段,就是将线性地址发个成不同区的start和end。
3.进程空间本质也是内核的一个数据结构对象,类似于PCB。地址空间也是需要被操作系统管理的。

在这里插入图片描述

在进程PCB里存着一个指针,叫做struct mm_struct的对象指针。这个对象指针就是指向进程地址空间的。

在这里插入图片描述

③.why

为什么要有进程地址空间呢?

在这里我们对进程的理解更深入了,进程的概念仍然是:内核数据结构+自己写的代码和数据。只不过这里的内核数据结构
除了PCB对象外,还有进程地址空间对象。

在没有进程地址空间以前,进程都是直接访问物理地址的,这很危险,进程管理和内存管理两个直接出现了强耦合。当内存管理出现了问题,进程就挂了,比如如果是越界访问,进程就直接挂掉,但就怕有人将物理地址空间修改了,内容改变了,这可能会影响其他进程。
在这里插入图片描述
而现在呢,有了进程空间地址,我们不再直接跟物理内存进行访问,而是通过虚拟内存进行访问,如果出现了问题,虚拟内存的机制会进行拦截除了的,并不会到达物理内存,这样就大大的保护了物理内存了。

1.所以进程地址空间可以让我访问内存时,增加一个转换的过程,在这个转换的过程中,可以对我们的寻址请求进行审查,一旦出现异常访问,直接拦截,该请求不会到达物理内存,保护物理内存。
2.可以让进程一统一的视角看待内部。因为物理内存是没有区域划分的,是可以随意任何地方开辟空间的,而虚拟内存则是划分区域的;最后可以让无序变有序。
3.减少了强耦合,一旦内存管理出现问题,会影响其他进程。

三.页表细节

①.标志位

页表是在哪呢?在CPU的一个叫cr3的寄存器里,里面存储着页表的起始地址。
我们要理解当进行需要使用页表时,肯定表面该进程正在运行使用中,那么肯定在CPU上运行着,所以进程直接通过CPU上的寄存器就可以找到该进程的页表。
在深入理解页表之前,我们先理解一个问题
【问题】为什么只读区的数据只读不给写的?静态成员为什么不能修改呢?代码是只读的?为什么呢?
对于物理内存来说,没有只读概念,都是可访问的,所以实现这个操作的关键在页表。

在页表中除了虚拟内存映射物理内存外,还有一个标识位。
表示该内存是否可以读写,r表示只读,rw表示可读可写。
所以对于代码区域的或者静态区的虚拟内存确实映射到物理内存上了,但页表还给它进行了标识r表示只读。这样该数据就只能是只读状态不可写。
在这里插入图片描述

②.缺页中断

我们知道进程挂起时,会将进程的代码和数据先放入磁盘中省出空间,给CPU使用,那么我们如何确定进程的代码和数据被放入磁盘里了呢?

在这里插入图片描述
对于虚拟内存,地址都可以先将加载到页表里,而物理内存可以先不加载进去,然后页表里存在一个标志位,用来表示该物理内存是否存在,0表示不存在,1表示存在。

所以当CPU需要访问某个数据时,首先会根据页表从虚拟地址转换到物理地址,如果发现页表里没有加载该数据的物理地址,页表里的标识位也为0.操作系统会给这个数据申请内存,然后将申请的内存地址加载到页表里,并将标识位改成1,然后CPU再重新访问页表映射到物理地址。这时就可以正常访问数据了,这个过程叫做页表中断。
在这里插入图片描述
所以对于进程来说,一开始没有数据加载到内存里,也是可以创建PCB内核数据结构的,等当真正访问数据时再将数据加载进来。
并且就算程序运行起来了,数据加载进来了,也不代表所有的数据都加载进来。

写时拷贝的本质也就是发生了缺页中断。

这里是引用

四.总结意义

当发生缺页中断时,内存会重新申请,页表的物理地址会被填充内存的释放等过程跟进程是没有关系的,进程不需要关系这些问题。
进程只需向虚拟内存申请空间,释放空间。如果页表中的物理地址不存在,就会发生缺页中断自动调用内存管理的功能,去向内存中申请空间。
所有进程地址空间和页表的存在,使得进程管理根本不需要关心内存管理。
在这里插入图片描述

1.总结进程地址空间意义:

这里是引用
2.什么是统一的视角看待内存呢?
在这里插入图片描述

3.并且我们可以从更深层去阐明进程之间为什么存在着独立性:虚拟地址可以完全一样,但物理地址不同!
在这里插入图片描述
4.进程地址空间的存在使得物理内存不再被看见!
在这里插入图片描述

相关文章:

【进程概念④】:进程地址空间(虚拟内存与物理内存)

【进程概念④】&#xff1a;进程地址空间(虚拟内存与物理内存&#xff09; 一.进程地址空间二.分页与虚拟地址①.what②.how③.why 三.页表细节①.标志位②.缺页中断 四.总结意义 一.进程地址空间 你觉得我们代码中写的数据都在哪存储着呢&#xff1f; 在内存里存着&#xff0…...

C语言内存四分区

四个区域&#xff1a;代码区&#xff0c;全局区&#xff0c;栈区&#xff0c;堆区 ①代码区 存放所写代码&#xff0c;二进制内容 ②全局区&#xff08;又分data区和bss区&#xff09; 存放全局变量&#xff0c;静态变量&#xff0c;常量 data区&#xff1a;已经初始化的全局变…...

数据可视化报表分享:区域管理驾驶舱

在零售数据分析中&#xff0c;区域管理驾驶舱报表是用来分析企业运营数据&#xff0c;以制定销售策略和提高利润。因此这张报表需要整合大量数据&#xff0c;数据整合、分析、指标计算的工作量极大&#xff0c;在讲究高效率、高度及时性的大数据时代&#xff0c;BI数据可视化分…...

解决pip安装包后但是Pycharm检测不到

首先要知道python找包的原理&#xff1a;原理 之后把一下代码打印一下&#xff1a; import sys print(sys.executable)# /usr/bin/python2 print(sys.path)# [/usr/lib/python2.7, /usr/lib/python2.7/dist-packages, /usr/local/lib/python2.7/dist-packages] print(sys.prefi…...

折纸问题

折纸的次数 —— 从上到下的折痕 本质上是中序遍历的问题&#xff0c;因为每一次在已有的折痕后折的时候&#xff0c;当前折痕上的折痕一定为凹&#xff0c;当前折痕下的折痕一定为凸 。实际模拟了一个不存在的二叉树结构的中序遍历。 注&#xff1a;折纸折几次整颗二叉树就有…...

mysql-面试50题-2

一、查询数据 学生表 Student create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10)); insert into Student values(01 , 赵雷 , 1990-01-01 , 男); insert into Student values(02 , 钱电 , 1990-12-21 , 男); insert into Student v…...

FoLR:Focus on Local Regions for Query-based Object Detection论文学习笔记

论文地址&#xff1a;https://arxiv.org/abs/2310.06470 自从DETR问询式检测器首次亮相以来&#xff0c;基于查询的方法在目标检测中引起了广泛关注。然而&#xff0c;这些方法面临着收敛速度慢和性能亚优等挑战。值得注意的是&#xff0c;在目标检测中&#xff0c;自注意力机制…...

【QT开发(15)】QT在没有桌面的系统中可以使用

在没有桌面的系统中&#xff0c;可以使用QT库。QT库可以在没有图形用户界面&#xff08;GUI&#xff09;的环境中运行&#xff0c;例如在服务器或命令行终端中。 这样就可利用Qt的&#xff1a; 对象模型&#xff0c;信号和槽容器类多线程和多进程网络编程 等...

『heqingchun-Qt的艺术-优雅界面设计开发』

Qt的艺术-优雅界面设计开发 效果图 一、新建Qt窗口工程 二、准备资源文件 1.图标资源 链接: 图标资源 2.Qss资源 链接: Qss资源 三、设计开发 项目源码链接: CSDN资源...

webGL编程指南 第四章 平移+旋转.RotatdTanslatedTriangle.html

我会持续更新关于wegl的编程指南中的代码。 当前的代码不会使用书中的缩写&#xff0c;每一步都是会展开写。希望能给后来学习的一些帮助 git代码地址 &#xff1a;git 本篇文章将把旋转和平位移结合起来&#xff0c;因为矩阵的不存在交换法则 文章中设计的矩阵地址在这里​…...

使用canvas实现时间轴上滑块的各种常用操作(仅供参考)

一、简介 使用canvas&#xff0c;模拟绘制时间轴区域&#xff0c;有时间刻度标尺&#xff0c;时间轴区域上会有多行&#xff0c;每行都有一个滑块。 1、时间刻度标尺可以拖动&#xff0c;会自动对齐整数点秒数&#xff0c;最小步数为0.1秒。 2、滑块可以自由拖动&#xff0c…...

Netty优化-扩展自定义协议中的序列化算法

Netty优化-扩展自定义协议中的序列化算法 一. 优化与源码1. 优化1.1 扩展自定义协议中的序列化算法 一. 优化与源码 1. 优化 1.1 扩展自定义协议中的序列化算法 序列化&#xff0c;反序列化主要用在消息正文的转换上 序列化时&#xff0c;需要将 Java 对象变为要传输的数据…...

【Java网络编程】二

本文主要介绍了传输层的UDP协议和TCP协议&#xff0c;以及在Java中如何通过Socket套接字实现网络编程&#xff08;内附UDP和TCP版本的回显服务器代码&#xff09; 一.网络通信 网络编程&#xff0c;就是写一个应用程序&#xff0c;让这个程序可以使用网络通信&#xff0c;这里就…...

通过IP地址可以做什么

通过IP地址可以做很多事情&#xff0c;因为它是互联网通信的基础之一。本文将探讨IP地址的定义、用途以及一些可能的应用。 IP地址的用途 1. 设备标识&#xff1a;IP地址用于标识互联网上的每个设备&#xff0c;这包括计算机、服务器、路由器、智能手机等。它类似于我们日常生…...

前端 CSS 经典:clip、clip-path

1. clip 1.1 clip: auto | inherit | rect auto&#xff1a;默认&#xff0c;不裁剪 inherit&#xff1a;继承父级 clip 属性 rect&#xff1a;规则四边形裁剪 1.2 clip: rect(top, right, bottom, left) 注意&#xff1a; 1.裁剪只对 fixed 和 absolute 的元素有效。 2.top&…...

android 如何判断已配对的蓝牙是否打开了互联网访问开关

最近遇到一个需求&#xff0c;要判断已配对的蓝牙是否打开了互联网访问的开关。 经查看源码&#xff0c;得出以下方法。 1. 首先要判断蓝牙是否打开 2. 已打开的蓝牙是否已配对 3. 验证是否真正打开 /*** 是否打开蓝牙互联网访问*/SuppressLint("MissingPermission&quo…...

在Linux上实现ECAT主站

在Linux上实现ECAT主站 引言介绍EtherCATSOEM 使用下载ECAT主站编译 引言 EtherCAT由一个主站设备和多个从站设备组成。主站设备使用标准的以太网控制器&#xff0c;具有良好的兼容性&#xff0c;任何具有网络接口卡的计算机和具有以太网控制的嵌入式设备都可以作为EtherCAT的…...

Spring Cloud之服务熔断与降级(Hystrix)

目录 Hystrix 概念 作用 服务降级 简介 使用场景 接口降级 服务端服务降级 1.添加依赖 2.定义接口 3.实现接口 4.Controller类使用 5.启动类添加注释 6.浏览器访问 客户端服务降级 1.添加依赖 2.application.yml 中添加配置 3.定义接口 4.Controller类使用 …...

HashMap 哈希碰撞、负载因子、插入方式、扩容倍数

HashMap 怎么解决的哈希碰撞问题&#xff1f; 主要采用了链地址法。具体来说&#xff1a; 每个哈希桶不仅存储一个键-值对&#xff0c;而是存储一个链表或树结构。这样&#xff0c;具有相同哈希值的键-值对可以被存储在同一个哈希桶中&#xff0c;并通过链表或树结构来解决碰…...

【Unity3D】Unity与Android交互

1 Unity 发布 apk 1.1 安装 Android Build Support 在 Unity Hub 中打开添加模块窗口&#xff0c;操作如下。 选择 Android Build Support 安装&#xff0c;如下&#xff08;笔者这里已安装过&#xff09;。 创建一个 Unity 项目&#xff0c;依次点击【File→Build Settings→…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...