Linux初识地址空间

前言

上一期我们对进程优先级、命令行参数以及环境和变量做了介绍!以前我们就提到过一个问题有了运行队列为什么还要有优先级?本期将带你揭晓!

本期内容介绍

虚拟地址空间的引入

虚拟地址空间的介绍

如何理解地址空间

为什么要有地址空间

如何进一步理解页表和写时拷贝

解决历史遗留问题

虚拟地址空间

1.1虚拟地址空间的引入

OK,我们先来看看这样的一段代码:

这段代码是创建了父子进程,分别打印其pid、ppid以及一个全局变量的值和地址, 5秒后子进程把g_val给修改成了300;OK,我们来看看结果:

这里的结果是,前5秒父子进程都是打印的100,5秒后子进程把g_val修改了变成了300, 所以以后子进程的g_val就是300,而父进程的不变!这一点也可以理解,我们知道进程=task_struct(PCB)+其代码和数据;fork之后产生了子进程,而子进程的本质是在操作系统中多了一个进程即多了一套task_struct(PCB)+代码和数据,而以前介绍过子进程的代码是可以继承父进程的,如果子进程不对数据修改,子进程和父进程共享数据(注意:这里可没说子进程继承父进程的数据!!);这里子进程虽然修改了数据但父子进程具有独立性,所以父子进程数据也得想办法独立,可以理解的!但是让我们震惊的根本就不是这个,而是父子进程的g_val的地址是一样的!按照以往的理解就是一个变量既等于100又等于300,这怎么可能??所以我们可以得出一个结论:上面g_val的地址绝对是物理地址!!!,不是物理地址(物理内存的地址)那是啥呢?其实这是虚拟地址!!

1.2虚拟地址空间的介绍

虚拟地址空间我们是学习过的,在C语言、以及C++的时候都是介绍过的;就是下面这个:

不过当时在C语言和C++没有介绍是因为,这个东西本身就不是语言的问题,而是操作系统层面的知识!例如上面的例子,如果没有学系统,看到上面的代码后三观直接震碎!OK,言归正传,继续上回到虚拟地址空间上,以前我们介绍过:当一个进程在被调度时,会先把他的代码和数据加载到内存,然后操作系统会为其创建一个PCB(task_struct)来描述该进程的属性,并把PCB以某种数据结构组织起来,方便管理,即"先描述,在组织"!其实,当一个进程加载到内存时系统并不会只创建一个PCB,还会创建地址空间和页表来一起管理该进程!

我们以前所有程序的地址都是虚拟地址,并非物理地址!这里的虚拟地址就是你虚拟地址空间的地址,每个进程再被加载前都会为其分配一个虚拟地址空间!

页表是进行虚拟地址和物理地址转换的!

页表和虚拟地址空间本质也是和PCB一样的进程内核数据结构,所以系统也会对其进行管理的,如何管理?先描述,在组织!

如下图:

OK,和以前的一样不在多说~!所以,有了虚拟地址空间和页表的介绍,我们就可以理解上述的g_val父子进程的地址为什么是一样的了!

fork之后有了子进程,即有了子进程的代码和数据、PCB、虚拟地址空间、以及页表!其中代码、PCB(pid、ppid等除外)、虚拟地址空间、页表都是继承自父进程的;此时,父进程和子进程的地址空间的内容是一模一样的,所以他们指向的数据也是一样的,即此时数据形成浅拷贝!也就是我们前面所说的父子进程共享数据,而后面子进程对数据修改了,此时操作系统检测到了之后会对子进程的数据进行写实拷贝(OS自主完成的,用户感受不到),然后让子进程修改,所以子进程修改的是父进程数据的拷贝,所以子进程修改后父进程的g_val不变!这也符合我们介绍的,进程具有独立性!

如下图:

OK,理解了这里就可回答下面的问题了!

1、如果父子进程不对数据进行修改,是不是父子进程共享的呢?

是的,刚刚上面介绍了,父子进程如果不对数据进行修改,他们是都是共享一份数据的!

2、为什么要实行写实拷贝?可不可以在创建子进程时,把父进程的数据全部给子进程拷贝一份?

写实拷贝的本质是一种按需申请,通过拷贝的时间顺序达到有效节省空间的目的!

例如,进程的数据有环境变量、命令行参数等这些子进程几乎是不会修改的,如果你直接在创建子进程的时候拷贝一份话,会造成不必要的空间浪费!因为这些东西很少修改,父子进程共享即可,如果等到子进程真正的需要修改的时候给他开空间,写入即可!另一方面,即使子进程真的有内存需要,例如他在5秒后要一段malloc或new的空间,如果是一开始给子进程拷贝一份的话,前5秒他不用,这样一来是不是在5秒的时间内浪费了这一块空间?系统说不一定在这5秒内可以拿着这些空间做更多的事情,如果是写实拷贝的话,一开始只给页表一个虚拟地址,其对应的物理地址可以不给,等到真正用的时候再去申请即可!这样就提升了内存实时的使用效率!

1.3如何理解地址空间?

地址空间的本质就是内核的一个struct结构体!内部有很多的start和end,表示某个区域的范围!

我们举个例子就可以理解了:

假设你是一个上小学的文静的小男生或小女生,你的同桌是一个非常邋遢的同学,是不是把这放桌上,把那放桌上,你有一次受不了了,就在桌子上画了一条38线, 假设桌子长100cm,38线是在50cm处;左边属于你,右边的属于他!此时你对你们的桌子进行了区域划分,同理,你有一块内存空间,要分为很多的区,是不是也可以向上面的38线一样分区!

假设你同桌今天又把鞋子放到你桌边上了,你一起之下,把38线向右移动了20厘米直接73开:

所以这样就把区域划分变成了对每个对象的start和end的修改!其实内核中也是类似这样的,OK,来看看内核中的地址空间的区域划分:

1.4为什么要有地址空间?

要理解这个问题就先得理解好地址空间!OK,还是来一个例子:

在遥远的漂亮国有一个土豪,他有n个私生子,这些私生子相互不知道对方的存在!现在土豪先找到大儿子,说Tom最近老爹听说你在微软上班了?大儿子说嗯,土豪说可以不愧是我儿子,好好干老爹我现在身价100亿美金,等以后都是你的!大儿子一听好呀好呀~!然后土豪又找到二儿子,他二儿子在考博士,土豪说儿子听说你在考律师的博士?二儿子说是的老爹,土豪同样又说,好好学等你以后成功了,老爹的这100亿都是你的,二儿子也是很高兴的同意了~!过了几天这个土豪又找到他的私生女,说小爱呀听说你在做珠宝生意?小爱说是的呢,然后同样的套路给小爱说老爹现在又100亿你好好干以后都是你的~!小爱也点了头,然后又找到了它的小儿子说儿子听说你在准备申请上大学??小儿子点了点头,土豪又说,你只要能够申请到中国的清华大学老爹的这100亿都是你的.....

这里的土豪就是操作系统,这里的每个私生子就是每个进程,土豪给每个私生子(进程)画的大饼就是虚拟地址空间!

理解了这些现在再来谈一下为什么要有地址空间!主要有以下3个原因:

1、将无序变有序,让进程以统一的视角看待物理内存,以及自己运行的各个区域!

2、进程管理和内存管理进行解耦

3、拦截非法的请求(对物理内存的保护)

4、使每个进程保持独立性

什么意思呢?就是通过虚拟地址空间可以让每一个进程都以为自己的数据永远在某个地址处(虚拟地址)无需关心物理内存在哪里,其实它的真实的数据可能在物理内存的另一地址处!这样进程就变得更加好管理进程和内存了,这其实也是一种封装和C++STL迭代器类似,看似都一样,其实底层天差地别!这样每个进程都觉得每一个进程都是操作系统的唯一,而其实并不是~!关于拦截非法的请求,也是举个例子:比如说数组越界,其实是虚拟地址空间映射到页表时页表就已经检查出来了,这样就防止了对物理内存的随便乱访问,即保护了物理内存!

1.5如何进一步的理解页表和写实拷贝?

关于页表,我们这里只是非常简单的介绍了一下,什么多级页表都没提,这里只是先简单的见一下,后面动静态库以及多线程会在次介绍的!!这想说的意思是不要把页表像的过于简单了!OK,页表不光是对虚拟与物理地址的映射,还可以对非法的请求进行拦截即权限标志位的检查、是否在内存等!OK,再举个栗子:

char* str = "hello";
*str = 'H';

这段代码一执行就挂了,原因是给静态区的常量字符串赋值了!OK,语言层面是这样讲的,但是现在的问题是为什么不能够对静态区的常量赋值呢?其实是在赋值的时候再页表的时候被页表给拦截了!因为页表内部有一个标记位标记的是该地址处的数据是否有相应的权限,常量区的数据那必然只有写权限,你一写入页表就拦截了反馈给OS,操作系统就把你的进程给搞挂了~!

也就是,如果你的进程在进京某种操作时,都会经过页表的检查,如果合法让你操作物理内存,否则反馈给OS,OS会交给判断处理!例如,你的代码比如说由于内存压力大给把一部分挂起到磁盘了,当你进程在访问时页表一查虚拟地址存在但是物理地址不存在,此时发生错误,交给OS,OS检查完后发现是发生了缺页中断;再比如说在写入时发现要该数据被多个进程同时引用,此时反馈给OS,发现需要写实拷贝!如果上述都不是就需异常处理!

1.6历史遗留问题

我们在以前刚刚接触子进程的时候,这段代码:

当时看到一个变量的值即是大于0又是等于0,感觉三观直接崩塌了,其实现在介绍了虚拟地址空间后,现在再来看是很好理解的,fork后要return xxx;本质是对同一个变量id的写入,不管是谁先返回即写入就会发生写时拷贝,然后父子进程有了自己独立的物理内存的id而正在虚拟地址层面上他们的地址还是一样的!

OK,本期内容就介绍到这里,好兄弟,我们下期再见~!

结束语:我们不应该被眼前的一些所谓的华丽所迷惑,更应坚守初心,一步步的朝目标前进!

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

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

相关文章

docker和docker compose 部署

一. 将微服务运行在docker上: 1.新建一个空文件夹docker-demo,在里面再新建文件夹app,在app目录下新建一个名为Dockerfile的文件。 2.编写Dockerfile文件 3.构建镜像 4.启动镜像 5.可以访问了。 二使用Dockerfile构建微服务镜像 1.将j…

数据库系统概念(第八周 第一堂)(规范化关系数据库设计)(强推学习!!!)

目录 前言 E-R模型质量低的深层原因 数据依赖 函数依赖 主属性/非主属性 逻辑蕴含与闭包 Armstrongs Axiom 求解F闭包算法 求解属性集闭包算法 属性集闭包的作用 候选码求解理论和算法 候选码求解理论 无关属性 检验方法 正则覆盖 关系模式的设计 关系…

Spark常见的可以优化的点

Shuffle 复用 # 1.以下操作会复用的shuffle结果,只会读一遍数据源 val rdd1 sc.textFile("hdfs://zjyprc-hadoop/tmp/hive-site.xml").flatMap(_.split(" ")).map(x > (x,1)).reduceByKey(_ _).filter(_._2 > 1) rdd1.count() rdd1.fil…

Python高级用法:路径与文件操作(os与pathlib)

路径与文件 前言导入包判断路径存在判断路径类型(判断文件还是文件夹)获取父路径写入读出文件获得路径中所有子文件/子文件夹获取文件扩展名获取多个文件扩展名获取路径的组件创建目录删除文件或空目录 前言 在Python中,os模块提供了与操作系…

美国裸机云站群服务器使用指南

在当今数字化时代,网站和应用程序的稳定运行对于企业和个人都至关重要。为了满足日益增长的业务需求,裸机云站群服务器成为了一个理想的选择。以下是美国裸机云站群服务器的使用指南,帮助您更好地利用这一强大的云服务。 一、选择信誉良好的云…

AI大模型在运动项目的深度融合和在穿戴设备的实践及未来运动健康技术发展

文章目录 1. 技术架构2. 模型选择2.1 LSTM(长短期记忆网络)2.2 CNN(卷积神经网络)2.3 Transformer 3. 数据处理数据预处理 4. 实时性要求4.1 边缘计算4.2 模型优化 5. 数据隐私与安全6. 深入分析AI大模型在穿戴设备的应用和未来发…

k8s中的pod域名解析失败定位案例

问题描述 我在k8s中启动了一个Host网络模式的pod,这个pod的域名解析失败了。 定位步骤 敲kubectl exec -it [pod_name] -- bash进入pod后台,查看/etc/resolv.conf,发现nameserver配的有问题。这里我预期的nameserver应该使用宿主机的&…

动态 SQL

动态 SQL 是 MyBatis 的强大特性之一&#xff0c;能够完成不同条件下不同的 sql 拼接。也就是说执行的 SQL 语句并不是固定的&#xff0c;而是不同人的不同操作执行的语句会有所差异。MyBatis 通过使用 标签 的方式来实现这种灵活性的。 <if>标签 例如在有一些网站进行…

【linux网络(四)】传输层协议详解(上)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux网络 1. 前言2. UDP协议…

CPN Tools学习——从平面网构建分层 PN

1.先创建平面petri网 创建如下petri网&#xff1a; CPN ide创建petri网真的舒服很多&#xff0c;但是教程又是CPN Tools的&#xff0c;我的想法是看两个版本能不能互通&#xff0c;在前者创建&#xff0c;在后者运行学习。 新增定义&#xff1a; colset E unit with e; 但…

Go模板页面浏览器显示HTML源码问题

<!--* Title: This is a file for ……* Author: JackieZheng* Date: 2024-06-09 17:00:01* LastEditTime: 2024-06-09 17:01:12* LastEditors: Please set LastEditors* Description:* FilePath: \\GoCode\\templates\\index.html --> <!DOCTYPE html> <html …

高并发ping多台主机IP

简介 社区或者是大型公司往往有成千上万或者几百台设备&#xff0c;保持设备始终在线对网络运维人员来说至关重要&#xff0c;然而一个一个登录检查&#xff0c;或者一个一个ping并不明智&#xff0c;累人且效率极低&#xff0c;并出错率高。花钱买检测服务当我没说。 shell编…

acwing 5575. 改变数值 | c++题解及解释

acwing 5575. 改变数值 题目 代码及解释 #include <iostream> #include <cstring> #include <algorithm> #include <unordered_map> using namespace std;const int N305; int a[N],b[N]; unordered_map<int,int>f[N]; const int INF1e9;int gc…

Dev C++ 安装及使用方法教程-干活多超详细

Dev C 是一款非常好用&#xff0c;简约的C/C开发工具。可以减少很多创建工程的繁琐步骤&#xff0c;很快的进行开发。对于只用于来写代码的人来说&#xff0c;是比较轻量以及极速的。 Dev C 是一个windows下的c和c程序的集成开发环境。它使用mingw32/gcc编译器&#xff0c;遵循…

Docker部署常见应用之大数据基础框架Hadoop

文章目录 Hadoop简介主要特点核心组件生态系统 Docker Compose 部署集群参考文章 Hadoop简介 Hadoop是一个开源框架&#xff0c;由Apache软件基金会开发&#xff0c;用于在普通硬件构建的集群中存储和处理大量数据。它最初由Doug Cutting和Mike Cafarella创建&#xff0c;并受…

质疑标普,理解标普,加入标普

上周我在文章里提到过&#xff0c;标普信息科技LOF(161128)出现套利机会。每天申购卖出&#xff0c;到现在一个账户56*6336润。 得益于美股七巨头轮流领涨&#xff0c;161128依旧坚挺&#xff0c;每天溢价都是10%&#xff0c;成交量1个多亿&#xff0c;场内新增份额才400万份&…

2024年黑龙江省特岗招聘公告出了!!!

2024年黑龙江省农村义务教育阶段学校特设岗位教师招聘822人公告 (1、网上报名 时间&#xff1a;6月17日9&#xff1a;00—6月22日17&#xff1a;00。 网址&#xff1a; https&#xff1a;//sfyz.hljea.org.cn&#xff1a;7006/tgjs 2、网上资格审查 资格审查时间&#xff1a;6月…

马克·雷伯特访谈:机器人的未来及波士顿动力的创新之路

引言 机器人技术作为现代科技的前沿领域&#xff0c;始终吸引着大量的关注与研究。波士顿动力公司作为这一领域的领军者&#xff0c;其创始人兼前CEO马克雷伯特&#xff08;Marc Raibert&#xff09;近日在主持人莱克斯弗里德曼&#xff08;Lex Fridman&#xff09;的播客节目…

[Mdfs] lc3067. 在带权树网络中统计可连接服务器对数目(邻接表+图操作基础+技巧+好题)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接&#xff1a;3067. 在带权树网络中统计可连接服务器对数目 2. 题目解析 挺有意思的一道题目&#xff0c;重点是要能够读懂题目&#xff0c;然后结合几个图相关的处理技巧即可拿下。 图存储&#xff1a;邻接表即可。无向无…

HP惠普暗影精灵10 OMEN Gaming Laptop 16-wf1xxx原厂Win11系统镜像下载

惠普hp暗影精灵10笔记本电脑16-wf1000TX原装出厂Windows11&#xff0c;恢复开箱状态oem预装系统安装包&#xff0c;带恢复重置还原 适用型号:16-wf1xxx 16-wf1000TX,16-wf1023TX,16-wf1024TX,16-wf1025TX, 16-wf1026TX,16-wf1027TX,16-wf1028TX,16-wf1029TX, 16-wf1030TX,16-…