• 进程地址空间详解



    空间布局图

    在这里插入图片描述

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

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

    所以对于进程地址空间是属于操作系统的概念!我们当时学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通过软件的方式,给进程提供一个软件视角,认为自己会独占系统的所有资源(内存)

  • 相关阅读:
    【Linux】网络配置详解
    java毕业设计面向大学生心理健康服务平台源码+lw文档+mybatis+系统+mysql数据库+调试
    【iOS-UIImagePickerController访问相机和相册】
    JVM堆内存释放不及时问题
    HTML静态网页作业——电影介绍-你的名字 5页 无js 带音乐
    web前端之零碎知识点、字符串、数组、基础知识
    基于JAVA的图书借阅管理平台【数据库设计、源码、开题报告】
    软考证书可积分落户、评职称、抵扣个税等,快来考一个吧!
    记一个 Android 14 适配引发的Android 存储权限问题
    EasyRecovery热门免费数据检测修复软件
  • 原文地址:https://blog.csdn.net/m0_57723028/article/details/127915645