• 进程地址空间详解



    空间布局图

    在这里插入图片描述

    首先有一个问题,我们曾经学过的程序地址空间是内存吗???

    答案是 它不是内存!!!
    程序地址空间的说法都不太准确,应该叫做进程地址空间!

    所以对于进程地址空间是属于操作系统的概念!我们当时学C语言的时候对这部分只是有了一个浅浅的认识,方便我们的理解!

    其实程序地址空间其实叫做进程地址空间,而进程是操作系统上的概念。因此,进程地址空间分为如上图所示的几个部分:

    栈区(stack): 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这 >些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
    堆区(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收 。分配方式类似于链表。
    数据段(静态区) ( static ) :存放全局变量、静态数据。程序结束后由系统释放。
    代码段: 存放函数体(类成员函数和全局函数)的二进制代码。

    为什么fork()会返回两个值

    #include 
    #include 
    
    using namespace std;
    int main()
    {
        int global = 100;
        pid_t id = fork();
        if (id == 0)
        {
            // child
            cout<<"id地址"<<&id<<endl;
            global = 200;
            cout << "我是子进程pid:" << getpid() << " 我要改global,global:" << global << " global地址:" << &global << endl;
        }
        else
        {
            //father
            cout<<"id地址"<<&id<<endl;
            cout << "我是父进程pid:" << getpid() << " 我的儿子是:" << id << " global:" << global << " global地址:" << &global << endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在调用fork创建子进程,返回时发生写实拷贝
    每一个进程都有一个自己的地址空间
    对于这个写实拷贝的个人理解就是,一班和二班都有一个叫小明的人,但是他俩不是一个人(因为班级不同),对应到进程地址空间里就是 虚拟地址一样但是对应的物理地址却不同(因为页表不同)
    在这里插入图片描述

    先来看一下一个代码的现象

    #include 
    #include 
    
    using namespace std;
    int main()
    {
        int global = 100;
        pid_t id = fork();
        if (id == 0)
        {
            // child
            global = 200;
            cout << "我是子进程pid:" << getpid() 
            << " 我要改global,global:" << global
             << " global地址:" << &global << endl;
        }
        else
        {
            //father
            cout << "我是父进程pid:" << getpid()
             << " 我的儿子是:" << id << " global:" << global
              << " global地址:" << &global << endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

    在C/C++中我们看到的地址是物理地址吗?

    我们可以得出一个结论:我们在C/C++中使用的地址,绝对不可能是物理地址!!!
    因为如果是物理地址,上图的情况是不可能产生的!!!

    为什么操作系统不让我直接看到物理内存呢?

    内存就是一个硬件,不能阻拦访问你访问!只能被动地进行读取和写入!
    因此如果我们能够直接访问甚至修改物理内存,将会造成不可预料的后果,因此为了安全起见,操作系统不会让我们直接访问物理内存。
    并且运用虚拟地址可以方便转换需要访问的物理地址,提高程序运行效率

    什么是进程地址空间

    每一个进程在启动的时候,都会让操作系统给它创建一个地址空间,该进程地址空间就是进程地址空间

    每一个进程都会有一个自己的进程地址空间!!
    那么操作系统要不要管理这些进程地址空间呢?
    那么怎么去管理呢?
    进程地址空间,其实是内核的一个数据结构,操作系统肯定会先描述在组织这些数据结构,mm_struct

    理解进程地址空间

    所以我们验证说程序地址空间是不准确的,准确的应该说成进程地址空间,那么我们应该怎么来理解呢?

    进程地址空间在逻辑上是一个抽象的概念,我们在谈这个概念之前我们需要引入一个进程独立性。

    进程独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰!
    所谓的地址空间:其实就是OS通过软件的方式,给进程提供一个软件视角,认为自己会独占系统的所有资源(内存)

  • 相关阅读:
    和iPhone14一样高的像素?全网首测OAK-1-MAX人工智能相机
    利用逻辑分析仪处理CAN协议数据
    redis 持久化
    如何选择专业的游戏开发公司?
    运维开发小白学习之路
    C Primer Plus(6) 中文版 第14章 结构和其他数据形式 14.7 向函数传递结构的信息

    【教3妹学算法-每日1题】设计有序流
    【React-Hooks进阶】useState回调函数的参数 / useEffect发送网络请求/ useRef / useContext
    Android数据库基础
  • 原文地址:https://blog.csdn.net/m0_57723028/article/details/127915645