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,本期内容就介绍到这里,好兄弟,我们下期再见~!

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

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

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

相关文章

3DMAX卷曲修改器Roller插件使用方法详解

3DMAX卷曲修改器Roller插件使用教程 3DMAX卷曲修改器Roller,用于创建卷曲形状建模,并可生成卷曲和展开动画。使创建诸如卷起和打开毯子、旗帜这样的动画变得非常简单。 【适用版本】 适用于3ds Max 2012及更高版本 【安装方法】 3DMAX卷曲修改器Roller…

QT

#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) ,Gcancle(new QPushButton("取消",this)) ,EmmEdit(new QLineEdit(this)) { ui->setupUi(this);…

UDS——诊断三要素

文章目录 诊断三要素一、请求1.1 带子功能的服务1.2 不带子功能的服务二、正响应(肯定响应)2.1 带子功能诊断请求的肯定响应格式2.2 不带子功能诊断请求的肯定响应格式三、负响应(否定响应)否定响应码诊断三要素 诊断主要包含请求、肯定响应和否定响应三个要素 “请求”由…

浙大版PTA Python程序设计 题目与知识点整理(综合版)

目录 第一章 一、高级语言程序的执行方式 二、变量赋值与内存地址 三、字符编码 3.1 Unicode 3.2 ASCII(American Standard Code for Information Interchange) 四、编程语言分类按照编程范式分类 4.1 面向过程语言 4.2 面向对象语言 五、原码…

【LeetCode最详尽解答】42-接雨水 Trapping-Rain-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家! 链接: 42-接雨水 直觉 通过可视化图形来解决这个问题会更容易理解和解决。 给定输入: height [0,1,…

力扣231. 2 的幂(位运算)

Problem: 231. 2 的幂 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.若为0和负数则直接返回false; 2.利用一个标志数mask令其为一,不断的算术左移同时和n做与(&)运算,统计n中二进制位为1的个数&a…

HDU - 5651 xiaoxin juju needs help(Java JS Python C C++)

题目来源 Problem - 5651 (hdu.edu.cn) 题目描述 众所周知,小新是一位才华横溢的程序员。当他还是小学六年级的学生时,他就知道回文字符串了。 今年夏天,他在腾讯实习。一天,他的领导来找小新帮忙。他的领导给了他一个字符串&a…

25 avl树

目录 底层结构avl树的概念节点定义插入旋转验证删除全性能 1. 底层结构 前面对map/multimap/set/multiset进行了简单的介绍,在其文档介绍中发现,这几个容器有几个共同点是:其底层都是按照二叉搜索树来实现的,但是二叉搜索树有自…

【CSS in Depth2精译】1.1 层叠

CSS 本质上就是声明规则,并让这些特定的规则在各种情况下生效。一个类添加到某个元素上,则应用这个类包含的这一些样式;元素 X 是元素 Y 的一个子节点,则应用另一些样式。浏览器于是根据这些规则,判定所有样式生效的具…

使用 C# 进行面向对象编程:第 9 部分

使用 OOP 的用户活动日志 应用程序背后的关键概念 在这一部分中,我们将使用之前学到的一些 OOP 概念。我们将创建一个小型应用程序。在继续之前,请阅读我的文章user-activity-log-using-C-Sharp-with-sql-server/。在本课程中,我们将再次使…

springboot+vue+mybatis教师工作审核系统+PPT+论文+讲解+售后

随着社会不断进步与发展,生活节奏不断加快,信息已经成为我们生活中不可缺少的一部分,很多学校需要掌握大量的信息来了解特定学生的需求,传统的做法是组织大量的人力物力对学生散发调查表,然后对收集的信息进行统计并得…

PHP调用阿里云OSS的SDK封装成服务的完整指南与问题解决

在现代Web开发中,使用云存储来管理和存储大量的静态文件已经成为常态。阿里云OSS(对象存储服务)是其中一个非常受欢迎的选择。在这篇文章中,我们将详细讲解如何在PHP项目中集成并使用阿里云OSS SDK。 #### 一、前期准备 在开始之…

SSH概念、用途、详细使用方法

还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,ech…

【安装笔记-20240616-Windows-Gpg4win 证书管理器】

安装笔记-系列文章目录 安装笔记-20240616-Windows-Gpg4win 证书管理器 文章目录 安装笔记-系列文章目录安装笔记-20240616-Windows-Gpg4win 证书管理器 前言一、软件介绍名称:Gpg4win主页官方介绍 二、安装步骤测试版本:Gpg4win 4.3.1下载链接安装界面…

调用第三方系统的签名设计与校验实例讲解与实践

在现代软件开发中,调用第三方系统API已经成为常见需求。为了保证数据传输的安全性和完整性,许多API采用了签名机制。本文将详细讲解如何设计与校验调用第三方系统的签名,以确保双方通信的安全和可靠。 #### 一、签名机制的意义 签名机制主要…

ElasticSearch地理空间数据了解

ElasticSearch地理空间数据了解 使用场景 Elasticsearch 的地理空间数据处理功能在现代社会中有着广泛的应用,以下是一些常见的使用场景和方向: 1. 位置搜索和导航 本地服务发现:应用程序可以使用 Elasticsearch 查找用户附近的餐馆、商店…

awd工具安装

fscan(漏洞扫描) 下载 下载地址: Releases shadow1ng/fscan GitHub 把下载的文件放到指定文件目录里, 在文件的位置打开cmd 输入 fscan64.exe -h 192.168.1.1/24 ok了 接下来说说fscan的使用 使用 1.信息搜集: 存活探测(icmp) 端口扫描 2.爆破功能: 各类服务爆破(…

Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器

系列文章目录 Django入门全攻略:从零搭建你的第一个Web项目Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解Django ORM深度游&#xff…

Java | Leetcode Java题解之第160题相交链表

题目: 题解: public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA null || headB null) {return null;}ListNode pA headA, pB headB;while (pA ! pB) {pA pA null ? headB : pA.next;pB …

几何公差的设计和选用

保证轴承的旋转精度,提出圆柱度; 这里的轴肩部面 为了测量方便,使用圆跳动代替垂直度公差方便一些。