怎样建设电子商务网站,制作一号店网站,工业设计公司招聘,国外设计网站怎么登陆引言:
北京时间#xff1a;2023/2/22#xff0c;离补考期末考试还有5天#xff0c;不慌#xff0c;刚午觉睡醒#xff0c;闹钟2点20#xff0c;拖到2点50#xff0c;是近以来#xff0c;唯一一次有一种睡不醒的感觉#xff0c;但是现在却没有精神#xff0c;因为听了…引言:
北京时间2023/2/22离补考期末考试还有5天不慌刚午觉睡醒闹钟2点20拖到2点50是近以来唯一一次有一种睡不醒的感觉但是现在却没有精神因为听了一首歌当然洗脸更重要天后孙燕姿的《直来直往》三天170遍上头感兴趣的小伙伴可以去尝试一下哦上篇博客我们学习了系统中环境变量等知识现在我们接着系统环境变量的知识来学习一下进程地址空间的相关知识 虚拟地址空间
什么是进程地址空间呢让我们带着这个疑问一步一步的来探索吧首先我们在以前的知识中学习过如果创建子进程fork函数并且明白进程其中的一个特性独立性
所以明白这两点看下图中的代码和运行结果就可以很轻松的搞定 搞定了上述的代码和运行结构此时我们就可以通过下述的代码和运行结果来引出进程地址空间的一个小知识点了就是为什么父进程和子进程之间的地址是一样的呢 看到上述代码我们可以发现利用进程的独立性此时一个进程改变全局变量并不会影响到另一个进程当中的全局变量了解了这点突然觉得进程真的是非常的神奇看起来就是一个独立的个体一样当然更神奇的是这两个进程的地址是一样的为了探索地址一样的问题此时我们就找到了进程地址空间的切入点从父子进程拥有相同的地址空间问题引出地址空间的概念接下来就让我们再次探索地址空间的知识吧
复习有关内存的知识
当我们从上述例子之中得到了有关虚拟地址空间的概念之后此时我们肯定是会有疑问的比如最大的疑问为什么要有虚拟地址空间电脑中不是存在内存物理地址为什么不使用内存物理地址呢 此时在学习虚拟地址空间的概念之前我们就先来复习一下以前学过的有关内存的相关知识首先内存也叫存储器是电脑中非常重要的硬件组成部分因为有了存储器才使电脑拥有的记忆功能并且存储器可以分为内存和外存磁盘这里我们具体讲一讲什么是内存内存也还可以进行细分分为只读内存ROM和随机存取内存RAM注意此时的ROM指的就是硬盘也是属于内存中的一种哦搞清了之间的关系我们来看看存储器的组成存储器主要是采用半导体器件和磁性材料构成存储器的最小单元是存储元由一个双稳态半导体电路或一个CMOS晶体管或磁性材料构成然后由若干个存储元可以构成一个存储单元最后存储器就是由许多的存储单元构成的并且每一个存储单元可存放一个字节的空间所以如果你的机器是一个32位的机器此时就物理上就有32根地址线有了32根地址线当电脑进行通电的时候就会产生32个正电/负电1/0此时就使我们的电脑有了32个由1/0构成的二进制序列通过组合此时就有2^32 次方中可能有了这么多的组合此时就可以把这些组合和我们的存储元给结合在一起通过各种二进制序列组合给存储元编号这种就使我们拥有的地址的概念所以如果是一个32位的机器此时他就有43亿左右2的32次方存储单元地址此时每个存储单元存放一个字节此时该存储器就拥有的4G左右的内存空间。所以也就导致了你如果想要使用内存就必须把对应的信息给转换成二进制序列这样才可以在内存中这么多的地址中寻找到对应的数据如下图所示
看到这幅图我相信大家对内存的概念应该会有更深层次的体会和认识吧所以在我们电脑中的内存也就是物理内存本质上就是如上图的形式进行数据的存储。
为什么要有虚拟地址空间
在了解为什么要有虚拟地址空间之前我们先来谈谈操作系统的特性和基本功能所有应用程序对硬件的操作都必须通过操作系统实现并且为了防止硬件被失控的应用程序滥用和向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备操作系统此时需要通过抽象进程、虚拟内存和文件等概念来实现如下图 文件是对I/O设备的抽象表示虚拟内存是对主存和磁盘I/O设备的抽象表示进程则是对处理器、主存和I/O设备的抽象表示
明白了上述知识引出关键概念进程是对处理器、主存和I/O设备的抽象
所以此时就有了当我们运行一个程序的时候操作系统会提供一个假象就好像系统上只有这个程序在运行。程序看上去是在独占地使用处理器、主存和I/O设备处理器看上去就好像是在不间断地一条一条地执行该程序中的指令即该程序的代码和数据是系统内存中唯一的对象所以进程是操作系统对一个正在运行的程序的一种抽象在一个系统上可以同时运行多个进程而每个进程都好像在独占地使用硬件。
所以此时我们就明白了一个进程在运行时是独占所有的系统资源的
有了上述的知识此时就可以引出我们想要学习的重点知识为什么要有虚拟地址空间理由如下 在虚拟内存出现之前程序寻址用的都是物理地址因此程序能寻址的范围是有限的具体寻址的范围是2^32也就是4G并且如果没有虚拟内存那么每次运行进程就需要分配4G的物理内存给该进程使用因为进程是对处理器、主存和I/O设备的抽象是独占使用内存的运行一个进程就需要把我们所有的内存供给其使用并且由于物理内存是有限的当有多个进程要执行的时候每个进程都需要分配4G内存独占的使用所有的硬件所以当内存被分配完之后没有得到分配资源的进程就只能等待当另一个进程执行完后再将等待的进程装入内存这种方式执行进程效率是非常低下的并且由于指令都是直接访问物理内存那么进程就可以修改其他进程的数据甚至会修改内核地址空间的数据所以这种直接访问物理内存的方式是非常的可怕的并且因为内存是随机分配的所以程序运行的地址也是不正确的。 所以根据以上的种种原因我们就需要引入一个叫虚拟地址空间的概念来尝试解决这些问题。
什么是虚拟地址空间
首先根据上述的知识我们知道了为什么要有虚拟地址空间的概念所以此时我们就正式来谈谈什么是虚拟地址空间概念每个进程创建加载的时候会被分配一个大小为4G的连续的虚拟地址空间虚拟的意思就是其实这个地址空间时不存在的仅仅是每个进程“认为”自己拥有4G的内存而实际上它用了多少空间操作系统就在磁盘上划出多少空间给它。 通过概念我们可以知道虚拟地址空间的本质在我们的电脑中是不存在的不像物理内存那样拥有存储单元每个单元一个字节它是通过映射的形式将对应的数据存储在内存之中具体说起来较为复杂这里先不做了解。让我们看图来加深对虚拟地址空间的认识如下图 每个进程看到的虚拟地址空间由大量准确定义的区构成如上图所示每个区都有专门的功能
此时我们就来一一简单介绍一下这些区域的功能 程序代码和数据区代码段例如此时我们在执行一个C程序对所有的进程来说代码是从同一固定地址开始紧接着的是和 C全局变量相对应的数据位置存放代码和数据区是直接按照可执行目标文件的内容初始化的 堆代码和数据区后紧随着的是运行时堆。代码和数据区在进程一开始运行时就被指定了大小与此不同当调用像 malloc 和free 这样的C标准库函数时堆可以在运行时动态地扩展和收缩。 共享库:大约在地址空间的中间部分是一块用来存放像C标准库和数学库这样的共享库的代码和数据的区域。共享库的概念非常强大这里先简单介绍。 栈:位于用户虚拟地址空间顶部的是用户栈编译器用它来实现函数调用。和堆一样用户栈在程序执行期间可以动态地扩展和收缩。特别地每次我们调用一个函数时栈就会增长;从一个函数返回时栈就会收缩。 内核虚拟内存:地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区域的内容或者直接调用内核代码定义的函数。相反它们必须调用内核来执行这些操作。
总虚拟内存的运作需要硬件和操作系统软件之间精密复杂的交互包括对处理器生成的每个地址的硬件翻译。基本思想是把一个进程虚拟内存的内容存储在磁盘上然后用主存作为磁盘的高速缓存
如何管理进程地址空间
通过上述的知识此时我们明白了什么是虚拟地址空间所以当我们想要执行一个程序的时候该程序被加载到内存中内存生成一个对应的PCBtask_struct结构体来管理该程序对应的代码和数据此时的PCB中就存放这该进程的全部信息此时就可以明白我们的操作系统管理任何东西都是通过先描述再组织的方式进行管理的总而言之就是生成一个有合适成员变量的结构体所以此时操作系统管理进程地址空间也是通过先描述再组织的形式这样此时就又有了一个新的结构体 mm_struct 专门给进程使用的结构体也就是操作系统专门用来管理进程的结构体所以我们上述所说的进程可以独占的使用系统资源本质上就是因为其被操作系统通过先描述再组织的方式形成了一个结构体就是一个内核数据结构而已
pcb和mm_struct和进程地址空间具体关系请看下图搞清关系就行
从上图可以看出我们的task_struct结构体中是有一个结构体指针指向着mm_struct进程结构体的
从物理内存理解虚拟内存
明白了上述的知识此时我们知道无论内存怎样虚拟化最后肯定是都要放在物理内存之中所以想要深入了解虚拟内存此时就需要从物理内存的方面去理解首先文章开始我们已经复习过了物理内存的知识这里就不多做介绍了我们只要明白32位的机器物理内存是通过2^32个字节的地址空间构成就行并且如图我们可以看出物理内存是连续的线性的每个字节的空间是独立的一个地址代表一个字节所以当我们此时开辟了一个整形类型int此时就需要在线性内存中占4个连续的地址因为一个地址只代表一个字节所以本质上开辟一个整形向线性内存申请了4个不同的地址地址连续理解这个我相信大家都有疑问因为平时我们在调式看变量地址的时候并不可以看到4个地址只能看到一个地址所以此时就需要把这两个概念给结合起来理解最终得出本质上是4个地址但是由于这些地址是连续的方便查找的所以操作系统只是把4个地址中的最下面编号最小的那个地址线性给给我们剩下的3个地址是默认存在只是你看不到而已并且此时系统想要通过我们看到的那一个地址找到剩下3个地址的话就需要识别出该变量的类型区别double、float、long通过各个类型规定的字节大小依次从内存中的地址向后读取例int我们就再向内存读取三个字节读取三个字节后就停止double就再向后读取7个字节这样我们就可以很好的把物理内存的地址给管理使用起来。
总地址空间是线性结构
当我们了解到了地址空间是线性的那么可以知道我们的虚拟地址空间应该也是线性的所以此时就如上述的虚拟地址空间图一样我们可以把虚拟地址空间给划分成一个一个的区域实现每个区域执行不同的功能又因为我们的操作系统会将进程给抽象成一个结构体mm_struct如下图 此时我们就知道操作系统中的进程结构体就是通过一个一个的作用区域的开始start和结束end来控制进程虚拟地址空间例如当code_start 100code_end 200此时在该代码段中的100和200之间的区域表示的就是我们的虚拟地址所以虚拟地址空间就是一个线性的结构并且此时我们可以把这个结构通过结构体的方式定义成一个具有区域划分的新结构并且可以通过改变某个区域的开始start和结束end来改变该区域的大小例如虚拟地址中的栈区和堆区的扩大缩小就是通过这种形式来完成的。注只是简单理解原理不会错只是系统操作起来远复杂
浅谈数据从虚拟地址空间拷贝到物理内存
这个问题是比较复杂的感兴趣的同学请看这篇博客大佬博客
每个进程启动之后操作系统都会自动生成一个该进程的页表用于存储的是虚拟地址和物理地址的映射然后通过和CPU上的 MMU 进行交互把虚拟地址翻译成物理地址进而存储在物理内存之中原理就是这样但是实际复杂n倍。
如下图所示 通过上图我们可以发现为什么修改子进程的值不会改变父进程的值原因就是当修改子进程中的值时内存会自己重新开辟一块空间给你然后把你的页表映射关系给改变此时页表映射了位置就是新的空间此时就可以实现子进程的值改变并且因为页表是独立的所以改变的只是物理内存和页表的映射关系不会改变原虚拟地址中的值所以此时就很好的证明了子进程和父进程同一地址但不同值的问题并且因为此时在物理内存中开辟了两块空间所以也解释了父子进程有两个返回值的问题。
使用虚拟地址空间的好处
1.防止地址随意访问保护物理内存与其它进程 2.将进程管理和内存管理进行解耦合本质上是为了提高操作系统效率和内存使用效率 3.可以让进程以统一的视角看待自己的代码和数据进而忽略内存中的地址位置提高运行效率 总结:系统中无论是什么东西本质就是为了提高操作系统的效率虚拟地址soso