• 【linux】——程序地址空间_终


    目录

    一、复习

    二、为什么要存在地址空间

    1、基本概念

    2、为什么能够有效的保护内存?

    3、物理空间、虚拟空间的申请区别

    4、重新理解挂起

    总结


    一、复习

    地址空间是一种内核数据结构,包含各个区域的划分

    我们要想一想,创建一个进程的过程

    1、先创建PCB进程控制块,在linux下就是创建task_struct

    2、使用struct mm_struct* mm指向虚拟内存

    3、页表映射物理内存


    同时页表不仅仅可以映射虚拟地址与物理地址,它还具有权限管理的功能,当我们进行非法访问其它位置的地址时,是没有权限进行读写的,因为Linux下一切皆文件,文件就要有相应的权限,页表就可以管理权限,如果是非法访问,页表就会告知操作系统,让操作系统终止该进程。


    CPU已经读取到了指令,那么就和该指令的物理地址毫无关系了,因为程序编译之后就已经有了地址,在程序内部,具有函数跳转,我们通过汇编知道,所谓的函数跳转,实际上就是该函数第一个元素的地址,而编译结束我们并没有对程序内部的虚拟地址进行替换,所以CPU只会关心指令的虚拟地址。

    二、为什么要存在地址空间

    1、基本概念

    凡是非法的访问或者是映射,操作系统都会识别出来并终止该进程。

    我们学习C语言时一定写过类似的代码

    const char* str = "Hello World"

    它是一个常量字符串,如果我们将‘H'修改为'h'时就会报错,这正是因为常量区的数据只有w权限

    页表规定了地址空间不同区域的读写权限不同。

    所有的进程崩溃,本质上就是进程退出,进程退出实际上是操作系统杀掉了这个进程。

    并且·地址空间有效的拦截了非法操作,也就有效的保护了物理内存。


    2、为什么能够有效的保护内存?

    因为地址空间和页表是操作系统创建并维护的,想使用地址空间和页表进行映射,也一定要在操作系统的监管下,它保护了物理内存中的合法数据,保护了各个进程及内核相关的有效数据。


    因为有地址空间和页表的存在,我们就可以对未来的数据进行任意位置加载。只要我们能够通过页表进行映射,我们实际上并不会关心它的物理内存。


    有了地址空间我们就可以将物理内存的分配和进程管理做到分离。内核的内存管理模块和进程管理模块完成了解耦合


    现在我们讲的内容和语言并不在同一层面上。

    我们讲的是底层,底层万变不离其宗,掌握了底层,语言层面都不是问题,因为无论使用哪种语言写的程序,最后都要变成进程,只要是进程就离不开这些内容。

    我们所学的C/C++的new,malloc空间,本质上是在虚拟地址空间申请空间,它申请的是mm_struct指向的地址空间。

    3、物理空间、虚拟空间的申请区别

    我们如果申请了空间但是我们不用它会浪费空间吗?

    这个问题需要分情况来考虑:

    如果我们申请的是物理空间,如果不用就会出现了空间浪费

    而我们申请的是虚拟空间,并不会出现空间浪费,因为有地址空间的存在,上层申请空间,其实是在地址空间上申请的,操作系统可以一个字节也不给你,当你真正对物理地址空间访问时,才会执行内存相关算法,分配空间。这种操作是由操作系统自动完成的(用户进程完全没有感知)。

    物理内存理论上可以任意位置加载,物理内存中几乎所有数据和代码在内存中是乱序的。

    正是因为页表将地址空间上的虚拟地址和物理地址映射,在进程的视角中,所有的内存都是有序的。地址空间将进程有序化


    进程要访问的物理内存中的数据和代码可能目前并没有在物理内存中,前面我们讲到的挂起态,就是例子。同样也可以让不同进程映射到不同的物理内存,从而实现了进程的独立性。

    总结:

            进程的独立性通过地址空间+页表的方式实现


    因为地址空间的存在,每个进程都会认为自己拥有4GB空间,并且进程的空间都是有序的,每个区间的地址通过页表映射到不同的区域,实现了进程独立,每一个进程都不知道其它进程的存在,也不需要知道。

    4、重新理解挂起

    进程加载到内存本质是创建进程,并不是必须立马将所有的程序的代码和数据加载到内存,并创建内核数据结构和建立映射关系。

    我们创建进程时,最极端的情况下甚至只有内核结构被创建出来了,代码和数据并没有加载到内存。

    补充一点:操作系统可以实现对程序的分批加载、分批换出

    举一个简单的例子,我们平时玩游戏,常见的游戏大小都是好几十G,而我们的电脑内存只有8G,16G,并不能一下子将整个游戏加载到内存中,游戏就通过分批加载的策略,先将开始界面等先加载到内存,游戏的开始界面一般只会加载一次,加载完就会被换出到磁盘。

    我们还要知道一个小知识点:页表映射的时候可不仅仅映射的是虚拟地址和物理地址的位置,它还会映射磁盘中的位置。因此我们所谓的换出,并不是将其再拷回磁盘,而是声明这块空间可用就好了,当再次使用时,直接再从磁盘中拷贝就可以了。


    总结


    以上就是今天要讲的内容,本文仅仅简单介绍了进程地址空间的相关知识。

  • 相关阅读:
    Semi-过渡金属硼化物的各向异性、电子结构和物理性能的研究
    Leetcode 1769. 移动所有球到每个盒子所需的最小操作数
    python+java病人跟踪治疗管理系统#计算机毕业设计源码
    golang 切片结构体多条件排序
    ​LeetCode解法汇总377. 组合总和 Ⅳ
    ios swift sqlite3 简单使用
    热门项目!知识付费小程序源码系统 带完整的安装代码包以及安装部署教程
    【一起刷题】环形链表
    2022年最新辽宁交安安全员考试题库及答案
    策略模式 + 工厂模式 + 门面模式 实现用户多类型支付功能
  • 原文地址:https://blog.csdn.net/m0_62179366/article/details/126878427