进程地址空间
目录
回顾C/C++语言的程序地址空间
感性认识虚拟地址空间
虚拟地址空间与物理空间如何建立映射关系
为什么要虚拟地址空间?
回顾C/C++语言的程序地址空间
在学习C/C++语言时我们知道了一个概念叫程序地址空间。通俗来说就是如下一张表,从中可以得知系统的几个区域:
现在有个问题,这个表是内存吗?来看个例子就知道了:
可以看到,一开始父进程和子进程对应打印的全局变量数值和地址都一样,奇怪的事情出现了:当全局变量的值在子进程中被改变后,父进程的变量地址和子进程的地址还是同一个,但是两个的值不一样!
这是不可想象的,之前讲进程的时候说了,进程具有独立性,多进程下进程间是互不干扰的,即使共用代码但也会根据条件判断语句分开执行。 一个物理地址对应的数据流只有一个,对应的值也只有一个,但是这里确实出现了一个地址对应两个不同值的情况。这只能说明一个事实:这里的地址不是物理地址!
这里的地址叫做虚拟地址,也叫线性地址或逻辑地址。这就回答了上面的问题,那不是物理意义的内存,而是虚拟内存,所以以前学语言的时候说的指针不是物理地址,而是虚拟地址。
感性认识虚拟地址空间
进程在运行的时候会有一个错觉,它觉得它是独占CPU资源的,实际上在我们看来根本不是这样,CPU每时每刻都在调度不同进程,不断进行着切换。
根据这一点我举个例子帮助感性理解:
有个大帮派势力暗中统治着几座城市,帮主手下有两个心腹,但是他们俩互相不知道对方的存在。
为了让两个心腹好好干活别想着觊觎帮主之位,帮主对心腹A说,我死后这个集团就交给你打理了;同时,他也对心腹B说了一样的话,相当于分别给他们俩画了个大饼,而他们两人都不知道帮主和另一个人也许下了承诺。于是两人好好干,有一天A对帮主说想要更多实权,帮主说反正我快走了到时候一切都交给你,但你现在先别急,于是A愉快地干活去了,B也经历了同样的事。
这里帮主就好比操作系统,两个心腹A,B就是进程,两个进程以为自己独占着操作系统资源,操作系统为了更好地调度他们,给他们画了大饼,这张饼也就是”进程地址空间“,当进程想要向操作系统多要点空间资源时,操作系统不能一次全给它(本身内存吃紧要节省空间)就会分批一次一次给空间——对应我们malloc/new开空间。
那么操作系统是如何画饼的呢?————还是类比刚刚的例子,实际上画饼就是在人的脑中构建蓝图,可以看成一个数据结构:
struct 蓝图
{char* who;char* when;char* target;
};
那么操作系统也是一样,是对进程地址空间做管理,管理的本质是先描述再组织,描述也一样用struct结构体描述起来,地址空间的本质就是内核的数据结构mm_struct
地址空间上有heap,stack等区域,那么操作系统是怎么在地址空间上将它们描述起来的呢?————下面再举个例子:
帮主的帮派很大管理着几个城市,但是同等大小的势力也存在,并和该帮派对抗着。为了不引起大规模的乱斗,两个帮派划地分界,谁都不准越界半步。那么用数据结构进行区域划分是这样的:
struct area //区域
{unsigned int A_start; //帮派A区域起始位置unsigned int A_end; //帮派A区域结束位置unsigned int B_start; //帮派B区域起始位置unsigned int B_end; //帮派B区域结束位置
};struct area partition = {1,50,51,100};
//帮派A区域 [1,50]
//帮派B区域 [51,100]
两个帮派定好地界后还是有问题,因为货物运输交易经常牵扯到边界附近地带,容易造成摩擦,所以经过商量将小镇T作为公共使用区域,两边都可涉足:
struct area partition = {1,45,55,100};
这是区域调整的方法。
类比以上,操作系统也是一个道理。
地址空间描述的基本空间大小是字节,32位下是2^32个地址,1个地址1字节,一共大概4GB空间。每一个字节都要有唯一的地址。
如此一来,操作系统就可以根据划分好的地址描述heap等区域:
struct mm_struct
{unsigned int code_start;unsigned int code_end;unsigned int stack_start;unsigned int stack_end;.......
};
假设mm_struct这个内核数据结构就是这样的,里面区域划分假定如上,总之默认占4GB大小。
code_start 到 code_end这段区域里面有很多地址,叫做虚拟地址。
想要调整区域,像例子中的设定公共区域,其实就是改变区域的起始地址和结束地址,比如要扩大stack区域,可以增加stack_end。我们写C/C++代码时,malloc/new空间实际上就是扩大堆区,free就是缩小堆区。
我们知道,进程在创建的时候操作系统会创建一个PCB内核数据结构task_struct,里面存了进程的相关信息如优先级...然后操作系统给进程 “画大饼” ,进程为了得到这块大饼,它的task_struct里面有个指针指向mm_struct。
虚拟地址空间与物理空间如何建立映射关系
这里牵扯到页表等相关概念,我们处理一下简单讲解。
我们已经知道磁盘上的程序会加载到内存,并且一字节对应内存上的一个物理地址空间。
假设mytest.exe程序大小是8KB,内存起始地址是0x1111 1111,那么虚拟进程地址空间是如何与物理内存建立映射关系的呢?————系统中有一个东西叫页表,可以建立映射。
关于页表,页等概念这里先不说,主要看进程地址空间。
虚拟地址空间的一个字节0xFF01 EEEC存到页表左边,与右边存物理地址空间的0x2100 1110对应。 假设我们写代码int a = 10; 这里&a就是虚拟地址,会对应虚拟进程地址空间的一个字节,再对应页表的数据,再与物理空间对应。当修改a的值,物理内存存储的值也被改变。
补充:
1、在Linux下,我们认为虚拟地址和线性地址是一个概念(在其它某些OS下不一样)。因为2^32个虚拟地址都是紧挨一起线性排布下去的。
2、再次画图理解整个过程
每个进程都有自己的task_struct和mm_struct以及页表,当然物理内存只有一个,通过上述方式建立联系。操作系统OS操控管理着一切,给进程 “画大饼”,让进程看似好像独享操作系统资源,坐拥2^32字节大小空间,但其实进程无法直接查看物理内存大小和占用情况,只能通过 mm_struct ---> 页表---->物理内存的方式,而进程胃口也比较小,一次开个10MB.100MB很多了,再多OS也不会再给进程空间了。
为什么要虚拟地址空间?
1、虚拟地址空间可以保护物理空间不被错误修改,提高了系统的安全性。
试想一下要是没有虚拟地址空间,用户直接访问物理空间会发生什么。
假设你想修改一个数据,但是你访问错位置了,将一块重要的数据给修改了;或者你写的程序出现野指针等错误,容易造成系统的崩溃。
刚刚提到的页表除了建立虚拟空间地址和物理内存的映射关系外,还有其他作用,其中之一是保护与拦截。
当进程做出违反操作系统的行为访问物理内存时,页表会进行拦截。因为进程不能直接访问物理内存,需要通过mm_struct--->页表,此时页表就可以拦截越界行为,保护物理内存。
2、虚拟进程地址的存在,可以更方便的进行进程与进程数据代码的解耦,保证进程的独立性。
这段话很抽象,我们用例子来理解。还记得上面父子进程的那个程序吗,在子进程内部改变了全局变量globol_val,子进程和父进程打印的变量数值不同但虚拟地址相同。
现在我们结合刚刚获取的知识再来深入理解一下为什么虚拟地址相同。
系统生成父进程后,再生成子进程,子进程是以父进程为模板构建出来的,tast_struct , mm_struct,页表都一样。它们里面的全局变量globol_val的虚拟地址都依据映射指向物理内存的同一地址,所以一开始执行的时候打印的变量数值一样地址也一样。
当子进程内想要改变全局变量globol_val, 要经过虚拟地址、页表访问物理内存,此时操作系统会做一个工作——拷贝物理内存对应位置的数据给它另一块地址,然后更改页表映射,将子进程虚拟地址映射指向新的物理内存地址,最后更改新的globol_val的值。
为什么操作系统要做这一步?————因为进程具有独立性,当一个进程对被共享的数据进行修改时会破坏独立性,影响其他共享数据的进程,所以为了让进程改变数据的同时不破坏独立性,操作系统将该进程的页表映射更改,所以产生了虚拟地址相同,但对应值不同的现象。
这里的拷贝方式叫做写时拷贝,它可以让不同进程的数据分离。
3、 虚拟地址空间可以让进程以统一的视角来看待进程对应的代码和数据等各个区域,方便使用。
编译器也是以同样的视角来编译代码(地址)。
问题:可执行程序内部代码有地址吗?————有。进入汇编可以查看代码对应的地址,并且在链接的过程中也需要代码地址与库链接。
既然可执行程序代码有地址,那这个地址是什么地址呢?是物理地址还是虚拟地址?————自然是虚拟地址,或者这里更准确的说应该叫逻辑地址。
磁盘上的可执行程序里面有一个main函数,其内部调用了fun函数,并且fun函数的地址是0x1122,main函数的地址是0xFEE0, 程序也有全局数据区,代码区等,32位平台下和上面讲的虚拟地址空间编址方式一样是以32位编址的。
可执行程序加载到内存,天然地就有了一个外部的物理地址,和程序内部编址方式一样的。在程序内部main函数寻址调用fun函数,外部物理内存也是一样通过物理寻址main函数调用fun函数。
所以我们现在有两套地址,标识物理内存中代码和数据的地址,还有在程序内部进行跳转的虚拟地址。
内存将进程数据加载到CPU,CPU收到数据包括main函数和fun函数的地址(注意:此时CPU接收到的地址是虚拟地址!因为CPU读取的是指令,指令内部就有地址),PC指针记录下fun函数的地址,CPU先拿着main函数的虚拟地址,到页表查表映射物理内存,找到对应的main函数的物理地址然后执行main函数。
这里有个问题:CPU执行出来的地址是物理地址还是虚拟地址?————是虚拟地址,虚拟地址通过页表映射到物理内存。再调用main函数内部的fun函数,根据PC指针保存的fun函数地址,CPU再通过页表映射物理内存,此时CPU出来的还是虚拟地址。这样就形成了一个循环。
CPU在这整个过程中没有见到过物理地址,全都是虚拟地址。
相关文章:
进程地址空间
目录 回顾C/C语言的程序地址空间 感性认识虚拟地址空间 虚拟地址空间与物理空间如何建立映射关系 为什么要虚拟地址空间? 回顾C/C语言的程序地址空间 在学习C/C语言时我们知道了一个概念叫程序地址空间。通俗来说就是如下一张表,从中可以得知系统的几…...
数楼梯(加强版)
数楼梯(加强版) 题目背景: 小明一天放学回家,看到从1楼到2楼共有n个台阶,因为好奇,他想尝试一下总共有几种方案到二楼?他可以1步,2步,3步的跳,不能跳3步以上. 他试了很多次都没有解决这个问题,于是请求聪明的你帮忙解决这个问题. 题目描述: 1楼到2楼楼梯有n级台阶。小明每…...
MySQL-数据类型
数据类型简介数据表由多列字段构成,每一个字段指定了不同的数据类型,指定了数据类型之后,也就决定了向字段插入的数据内容。不同的数据类型也决定了 MySQL 在存储它们的时候使用的方式,以及在使用它们的时候选择什么运算符号进行运…...
剑指 Offer 32 - II. 从上到下打印二叉树 II(java解题)
剑指 Offer 32 - II. 从上到下打印二叉树 II(java解题)1. 题目2. 解题思路3. 数据类型功能函数总结4. java代码5. 踩坑记录1. 题目 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。 例如: 给定二叉…...
C#网络爬虫开发
1前言爬虫一般都是用Python来写,生态丰富,动态语言开发速度快,调试也很方便但是我要说但是,动态语言也有其局限性,笔者作为老爬虫带师,几乎各种语言都搞过,现在这个任务并不复杂,用我…...
Fastjson 总结
0x00 前言 这一篇主要是针对已经完成的fastjson系列做一个知识点总结,一来是为了更加有条理的梳理已经存在的内容,二来是为了更好的复习和利用。 0x01 Fastjson基础知识点 1.常见问题: 问:fastjson的触发点是什么?…...
文件路径模块os.path
文件路径模块os.path 文章目录文件路径模块os.path1.概述2.解析路径2.1.拆分路径和文件名split2.2.获取文件名称basename2.3.返回路径第一部分dirname2.4.扩展名称解析路径splitext2.5.返回公共前缀路径commonprefix3.创建路径3.1.拼接路径join3.2.获取家目录3.3.规范化路径nor…...
Kerberos简单介绍及使用
Kerberos作用 简单来说安全相关一般涉及以下方面:用户认证(Kerberos的作用)、用户授权、用户管理.。而Kerberos功能是用户认证,通俗来说解决了证明A是A 的问题。 认证过程(时序图) 核心角色/概念 KDC&…...
DOM编程-全选、全不选和反选
<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>全选、全不选和反选</title> </head> <body bgcolor"antiquewhite"> <script type"text/jav…...
C++11可变模板参数
C11可变模板参数一、简介二、语法三、可变模版参数函数3.1、递归函数方式展开参数包3.2、逗号表达式展开参数包一、简介 C11的新特性–可变模版参数(variadic templates)是C11新增的最强大的特性之一,它对参数进行了高度泛化,它能…...
Linux多线程
目录 一、认识线程 1.1 线程概念 1.2 页表 1.3 线程的优缺点 1.3.1 优点 1.3.2 缺点 1.4 线程异常 二、进程 VS 线程 三、Linux线程控制 3.1 POSIX线程库 3.1 线程创建 3.3 线程等待 3.4 线程终止 3.4.1 return退出 3.4.2 pthread_exit() 3.4.3 pthread_cancel…...
Webpack5 环境下 Openlayers 标注(Icon) require 引入图片问题
Webpack5 环境下 Openlayers 标注(Icon) require 引入图片问题环境版本Openlayers 使用 require 问题Webpack5 正确配置构建新环境的时候,偶然发现 Openlayers 使用 require 的方式加载图片(Icon)报错,开始…...
Zookeeper安装部署
文章目录Zookeeper安装部署Zookeeper安装部署 将Zookeeper安装包解压缩, [rootlocalhost opt]# ll 总用量 14032 -rw-r--r--. 1 root root 12392394 10月 13 11:44 apache-zookeeper-3.6.0-bin.tar.gz drwxrwxr-x. 6 root root 4096 10月 18 01:44 redis-5.0.4 …...
Cow Acrobats ( 临项交换贪心 )
题目大意: N 头牛 , 每头牛有一个重量(Weight)和一个力量(Strenth) , N头牛进行排列 , 第 i 头牛的风险值为其上所有牛总重减去自身力量 , 问如何排列可以使最大风险值最小 , 求出这个最小的最大风险值&am…...
MySQL:为什么说应该优先选择普通索引,尽量避免使用唯一索引
前言 在使用MySQL的过程中,随着表数据的逐渐增多,为了更快的查询我们需要的数据,我们会在表中建立不同类型的索引。 今天我们来聊一聊,普通索引和唯一索引的使用场景, 以及为什么说推荐大家优先使用普通索引…...
Spring Cloud alibaba之Feign
JAVA项目中如何实现接口调用?HttpclientHttpclient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持Http协议的客户端编程工具包,并且它支持HTTP协议最新版本和建议。HttpClient相比传统JDK自带的URL Connection&a…...
零信任-Google谷歌零信任介绍(3)
谷歌零信任的介绍? "Zero Trust" 是一种网络安全模型,旨在通过降低网络中的信任级别来防止安全威胁。在零信任模型中,不论请求来自内部网络还是外部网络,系统都将对所有请求进行详细的验证和审核。这意味着每次请求都需…...
Numpy基础——人工智能基础
文章目录一、Numpy概述1.优势2.numpy历史3.Numpy的核心:多维数组4.numpy基础4.1 ndarray数组4.2 内存中的ndarray对象一、Numpy概述 1.优势 Numpy(Nummerical Python),补充了Python语言所欠缺的数值计算能力;Numpy是其它数据分析及机器学习库的底层库&…...
电商仓储与配送云仓是什么?
仓库是整个供给链的关键局部。它们是产品暂停和触摸的点,耗费空间和时间(工时)。空间和时间反过来也是费用。经过开发数学和计算机模型来微调仓库的规划和操作,经理能够显著降低与产品分销相关的劳动力本钱,进步仓库空间应用率,并…...
【零基础入门前端系列】—HTML介绍(一)
【零基础入门前端系列】—HTML介绍(一) 一、什么是HTML HTML是用来描述网页的一种语言HTML指的是超文本标记语言:HyperText Markup LanguageHTML不是一种编程语言,而是一种超文本标记语言,标记语言是一套标记标签(ma…...
Elasticsearch索引库和文档的相关操作
前言:最近一直在复习Elasticsearch相关的知识,公司搜索相关的技术用到了这个,用公司电脑配了环境,借鉴网上的课程进行了总结。希望能够加深自己的印象以及帮助到其他的小伙伴儿们😉😉。 如果文章有什么需要…...
使用Python,Opencv检测图像,视频中的猫
使用Python,Opencv检测图像,视频中的猫🐱 这篇博客将介绍如何使用Python,OpenCV库附带的默认Haar级联检测器来检测图像中的猫。同样的技术也可以应用于视频流。这些哈尔级联由约瑟夫豪斯(Joseph Howse)训练…...
浅谈域名和服务器集约化管理的误区
一个正常的网站通常由域名、网站程序、服务器三个部分组成,网站程序由单位开发设计,而域名和服务器则需要租用购买,那么域名和服务器之间的关系是什么?如何实现域名和服务器的有效管理呢? 服务器和域名的关系 服务器…...
迪赛智慧数——柱状图(正负条形图):20212022人才求职最关注的因素
效果图从近两年职场跳槽方向看,相比此前人们对高薪大厂趋之若鹜,如今职场人更关注业务前景。根据相关数据显示,职场人求职最关注的因素中,“薪资福利”权重下降,“个人发展”权重上升,“业务前景”首次进入…...
网络安全-黑帽白帽红客与网络安全法
网络安全-黑帽白帽红客与网络安全法 本章内容较少,因为刚开端。 黑客来源于hacker 指的是信息安全里面,能够自由出入对方系统,指的是擅长IT技术的电脑高手 黑帽黑客-坏蛋,研究木马的,找漏洞的,攻击网络或者…...
Xpath元素定位之同级节点,父节点,子节点
XPath学习:轴(8)——following-siblingXPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。推荐一个挺不错的网站:htt…...
华为OD机试 - 挑选字符串(Python)| 真题+思路+代码
挑选字符串 题目 给定 a-z,26 个英文字母小写字符串组成的字符串 A 和 B, 其中 A 可能存在重复字母,B 不会存在重复字母, 现从字符串 A 中按规则挑选一些字母可以组成字符串 B 挑选规则如下: 同一个位置的字母只能挑选一次, 被挑选字母的相对先后顺序不能被改变, 求最…...
python笔记-- “__del__”析构方法
-#### 1、基本概念(构造函数与析构函数) 特殊函数:由系统自动执行,在程序中不可显式地调用他们 构造函数: 建立对象时对对象的数据成员进行初始化(对象初始化) 析构函数: 对象生命期…...
支付系统核心架构设计思路(万能通用)
文章目录1. 支付系统总览核心系统交互业务图谱2. 核心系统解析交易核心交易核心基础交易类型抽象多表聚合 & 订单关联支付核心支付核心总览支付行为编排异常处理渠道网关资金核算3. 服务治理平台统一上下文数据一致性治理CAS校验幂等 & 异常补偿对账准实时对账DB拆分异…...
python实现mongdb的双活
如何用python实现mongdb的双活,两个数据库实时同步? 可以使用Pymongo库,它可以提供同步的API来实现MongoDB的双活,两个数据库实时同步。还可以使用MongoDB的复制集功能来进行实时同步。 Pymongo库提供什么同步的API来实现MongoD…...
北京住房和城乡建设委员会网站自住房/业务推广平台
前言: 之前,我们已经通过经历了类和对象(上)和类和对象(中)的学习,使我们对类和对象这一概念打下了坚实的基础,今天我们要做的便是对类和对象进行收尾工作,本篇之后关于…...
微网站后台录入/今日热点新闻事件2022
一、类加载器 ClassLoader 能根据需要将 class 文件加载到 JVM 中,它使用双亲委托模型,在加载类的时候会判断如果类未被自己加载过,就优先让父加载器加载。另外在使用 instanceof 关键字、equals()方法、isAssignableFrom()方法、isInstance(…...
最早做团购的网站/精准营销案例
ioriiod0/orchid GitHub什么是orchid?orchid是一个构建于强大的boost库基础上的C库,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型。什么是协程:协程,顾名思义,协作式程序,其思想是&…...
smluntan论坛wordpress/宁波网络推广软件
原标题:Python 中 _new__方法详解及使用 __new__ 的作用 在Python中__new__方法与__init__方法类似,但是如果两个都存在那么__new__先执行。 在基础类object中,__new__被定义成了一个静态方法,并且需要传递一个参数cls。Cls表示需…...
百度云 做网站/公司seo是什么级别
http://www.cnblogs.com/skychen1218/背景本公司是.Net项目,在.Net可选的MQ比较少,主要Kafka和RabbitMQ,RabbitMQ我也是使用多年了,最近的Kafka广告与流行度打得使我也是无法无视,因此也是花了点时间收集了资料做了些对…...
wordpress更新之后字体发生变化/杭州seo关键字优化
如何截取视频片段,只截取视频中间的一部分.我们从网上下载了一些视频,想要进行编辑,剪切之类的,往往会在选择软件上眼花缭乱。现在市面上有很多视频编辑的软件,有共享的,免费的,po解版的&#x…...