【Linux】虚拟地址空间

news2025/1/17 8:46:35

文章目录

  • ❓什么是虚拟地址空间?
      • 😊我们先来看这样的一个程序:
      • ⚠️感性的认识虚拟地址空间
  • 😊Linux具体是怎么实现进程地址空间的
  • ❓为什么会存在虚拟地址空间?

❓什么是虚拟地址空间?

虚拟地址空间是操作系统为了实现进程管理所设定的一种虚拟化解决方案,通过虚拟地址空间可以让每个进程都认为自己可以独占系统资源。

学过C语言的肯定听说C/C++地址空间、里面有代码区、已初始化区、未初始化区、堆区、栈区等空间。堆向下生长、栈向上生长等等。但是其实我们对于他们的了解其实还并不全面。

😊我们先来看这样的一个程序:

#include <stdio.h>
#include <unistd.h>

int global_value = 100;

int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        printf("fork error\n");
        return 1;
    }
    else if(id == 0)
    {
        int cnt = 0;
        while(1)
        {
            printf("我是子进程, pid: %d, ppid: %d | global_value: %d, &global_value: %p\n", getpid(), getppid(), global_value, &global_value);
            sleep(1);
            cnt++;
            if(cnt == 10)
            {
                global_value = 300;
                printf("子进程已经更改了全局的变量啦..........\n");
            }
        }
    }
    else
    {
        while(1)
        {
            printf("我是父进程, pid: %d, ppid: %d | global_value: %d, &global_value: %p\n", getpid(), getppid(), global_value, &global_value);
            sleep(2);
        }
    }
    sleep(1);
}

在这里插入图片描述
在子进程没有改变全局变量global_value的时候,可以看到父子进程之前的global_value以及global_value的地址都是一样的;
在子进程改变全局变量global_value之后,可以看到父子进程的值有了区别,子进程的值是300,父进程是100,因为我们知道进程具有独立性,再往后看奇怪的事情发生了,为什么父子进程的这个全局变量global_value的地址是一样的呢?
既然地址一样那为什么值也不是一样的呢?所以说我们曾经学习过的语言级别的地址(指针)绝对不是在硬件层次上对应的物理地址。
⚠️对于这段代码奇怪的现象的解释在 为什么会存在虚拟地址空间?中的第二条有介绍。
那上边用&取出的这个地址是什么?其实这个地址叫做虚拟地址

⚠️感性的认识虚拟地址空间

首先,每个进程都会认为自己是独占系统资源的,事实上并不是,操作系统会给每个进程“画饼”,就好比提前跟进程说,我这些系统的资源都是你的,但事实上每个进程一般也用不了这么多的资源,操作系统也不可能把所有的资源给一个进程,那么虚拟地址空间其实也就是操作系统给每个进程画的大饼。

那么操作系统是怎么给每个进程“画饼”的呢?
首先给每个进程画饼,每个进程需要被管理,同时给每个进程画的大饼也就是进程地址空间(进程的虚拟地址空间)它也要被管理好,乱画饼万一不够了怎么办?怎么管理呢?管理的本质就是对数据的管理,一说到管理那就要提到先描述再组织了,是一个建模的过程,进程地址空间的本质其实就是Linux内核的一种数据结构(mm_struct)。

进程地址空间描述的基本空间大小是字节。在32位操作系统下,就有 2 32 2^{32} 232个地址,一个地址占一个字节,那么总共就是4GB的空间范围。每一个地址都要有唯一的标识,那么其实用32位二进制序列就可以唯一标识这些地址。这些序列就是所谓的虚拟地址


😊Linux具体是怎么实现进程地址空间的

我们知道操作系统管理每个进程时要用PCB结构体(在Linux中是task_struct)来管理,而task_struct中就包含操作系统给每个进程画的大饼mm_struct(也就是对每个进程的进程地址空间做管理的结构体),在32位系统下这个mm_struct假装把4GB的虚拟空间全部都给了每个进程。此时每个进程都会认为自己是独占系统资源的。

下面是Linux内核源代码PCB中的mm_struct结构体的指针。
在这里插入图片描述
我们转到mm_struct的定义来看,mm_struct内部有很多无符号整形变量start和end来标识每个区域的大小,假如栈区的start和end分别是1和4,那么栈区域起始地址就是1,栈区域的结束地址就是4,这之间的区域就归该进程的栈使用,其他区域也是这样的。就是下面红圈圈住的一部分代码。
在这里插入图片描述
在这里插入图片描述

就像其他区域当进程被创建之后就不可以被修改了,但是栈区和堆区是可以被修改的,那么其实这两个区域的区域调整本质上也就是修改各个区域的start和end的值即可。

❓为什么会存在虚拟地址空间?

1️⃣如果让进程直接访问物理内存,万一进程越界直接非法访问我们在磁盘的重要信息呢?所以说让进程直接访问物理内存是非常不安全。页表让虚拟地址和物理地址做映射的同时还会监视进程非法的访问,一旦有非法的访问那么就会被拦截。

2️⃣地址空间的存在可以更方便地进行进程和进程的数据代码的解耦,保证了进程独立性这样的特征。
解释:
就像文章一开始写的那个父子进程的程序,为什么会出现那样的现象呢?
在这里插入图片描述

因为在创建子进程的时候,子进程把父进程的进程地址空间全部都拷贝了一份,在子进程没有改变global_value的值之前,两个进程&global_value确实都一样,都位于虚拟地址的同一个地址上,当然此时通过页表转换成的物理地址也是一样的,然而当子进程改变了global_value的值之后,父进程就受到影响了,但是我们知道 进程具有独立性 ,一个进程对被共享的数据做了修改,如果影响了其他进程,那么进程就不具有独立性了。操作系统不允许这样的事情发生,在子进程把global_value的值修改了之后,操作系统会更改子进程页表原来的global_value与物理地址之间的映射关系,重新在物理地址(物理内存)的其他位置寻找一块空间来存放子进程改变之后的global_value的值。
但整个过程与虚拟地址没有关系,所以我们才会看到父子进程的这个&global_value的值一样,而global_value的值不一样的现象。
我们将任何一个进程尝试写入,操作系统先进行数据拷贝,然后更改页表映射,再让进程进行修改的现象叫做写时拷贝

所以说操作系统为了保证进程的独立性,做了很多工作,也是煞费苦心。不同的PCB、不同的进程地址空间、通过地址空间、通过页表、让不同的进程映射到不同的物理内存处。

通过前面对于进程的讲解我们知道:进程=内核数据结构+进程对应的代码和数据
内核数据结构像PCB、以及PCB内的进程地址空间是独立的。进程对应的数据在需要独立的时候通过写时拷贝也能进行独立,所以操作系统就让进程理所当然的具有了独立性

3️⃣通过虚拟地址空间,让进程以统一的视角来看待进程对应的代码和数据等各个区域。也就是说每个进程看待各个区域像是栈区、堆区的视角都是一样的,但他们通过页表映射就可以映射到物理内存的不同区域。编译器也以虚拟地址空间这样的视角统一地进行编译代码。规则是一样的,所以编译完即可直接使用。

解释:
虚拟地址空间的这套规则不能认为只有操作系统才会遵守对应的规则编译器也要遵守对应的规则。编译器编译代码形成.exe可执行程序的时候,也是按照虚拟地址空间的方式进行对应的代码和数据进行编址的。那么其实在磁盘上的可执行程序内部早就有地址了,程序在链接的时候就已经把地址填入到你自己的可执行程序里,让你的可执行程序在运行的时候可以找到对应的内容。(磁盘中可执行程序里的地址就是逻辑地址。)

补充:

  • 虚拟地址空间是操作系统给进程画的大饼,进程要被管理,PCB内的进程地址空间也要被管理,所以都是先描述再组织。然后每一个进程都有它对应的进程地址空间,经过进程对应的页表映射,来完成CPU在进程的上下文当中进行寻址的工作。
    在这里插入图片描述
  • 程序加载到内存中,自然就具有了一个外部的物理地址。
  • 物理内存其实现在有两套地址
    1.标识物理内存中代码和数据的地址
    2.在程序内部互相跳转的时候用的虚拟地址
    在这里插入图片描述

进程地址空间上的虚拟地址和物理地址之间是通过页表来一一映射,建立映射关系的,每个进程是直接看不到内存上的物理地址的。


请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93629.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Node.js计算机毕业设计高校学生选课系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

Android 跨应用发送自定义广播

话不多说&#xff0c;直接看效果图和代码&#xff01; 一、效果图 1、未发送广播之前&#xff0c;两个APP的主界面图&#xff1b; 2、发送之后&#xff0c;文本框内容改变。 二、代码 1、创建第一个APP &#xff08;1&#xff09;MainActivity中代码如下&#xff1a; p…

分享篇:第十届“泰迪杯”数据挖掘挑战赛-农田害虫图像识别(特等奖)一

1.1 赛题背景 昆虫的种类浩如烟海&#xff0c;农田常见的昆虫是人工生态系统的重要组成部分。分辨益 虫和害虫&#xff0c;保留益虫&#xff0c;消灭害虫&#xff0c;对于减轻害虫对农田的生产危害有重要意义。常见 农田害虫共有 138 种&#xff0c;天敌昆虫则为 40 种。病虫害…

D-UNet:一种用于慢性脑卒中病变分割的维数融合U型网络

摘要 二维卷积神经网络忽略了医学图像的三维信息&#xff0c;而三维卷积神经网络对计算资源的需求过大。而本文提出一种新的结构&#xff0c;称为维度融合网络&#xff08;D-UNet&#xff09;这个网络在编码阶段创新的结合了二维和三维卷积。所提出的网络结构实现了比2D网络更…

C语言快速过渡C++

下面只讲干货&#xff0c;方便C语言初学者快速上手cpp来刷算法题&#xff0c;如果是希望系统学习cpp的不建议继续阅读&#xff0c;仅限于快速使用 文章目录using namespace stdcin cout 头文件变量声明bool变量const定义常量string类字符串的定义与拼接字符串的输入字符串的处理…

Qt扫盲-QStackedWidget理论总结

QStackedWidget理论总结1. 简述2. 布局用法3. 页面切换4. 常用功能1. 简述 QStackedWidget和QTabWidget的功能类似&#xff0c;都是为解决大量的控件在一个页面上可能显示不出来&#xff0c;同时呢&#xff0c;这些控件也可以按一定方式分类&#xff0c;我们就可以把这些控件分…

JAVA文件基本操作与概念

文件的概念 狭义的文件&#xff1a; 存储在硬盘上的数据&#xff0c;以文件为单位&#xff0c;进行组织&#xff1b;文件夹也叫做"目录"&#xff0c;也是一种特殊的文件(文件里存储的也是文件) 这章笔记的内容都是指狭义的文件 广义的文件&#xff1a; 操作系统…

Docker安装emqx详解(配置SSL证书、开启WSS、鉴权)

EMQX 是一款大规模可弹性伸缩的云原生分布式物联网 MQTT 消息服务器。 1 端口介绍 1883&#xff1a;MQTT 协议端口8084&#xff1a;MQTT/SSL 端口8083&#xff1a;MQTT/WebSocket 端口8080&#xff1a;HTTP API 端口18083&#xff1a;Dashboard 管理控制台端口 2 拉取镜像 …

视频文件转M3U8

前言 前段时间遇到一个播放视频的项目&#xff0c;为了防止登录的用户下载项目的视频&#xff0c;所以需要对视频加密&#xff0c;即使用户下载也不能播放&#xff1b;因为前端采用videojs&#xff0c;最后确认方案是将mp4转m3u8文件格式&#xff0c;来实现视频文件加密播放。下…

公共用房管理系统有哪些管理功能?

数图互通房产管理 数图互通公共用房管理系统的管理功能范围包括: 1、对全部公房进行图形化、电子化、规范、动态化管理。 2、房屋数据定义:可对校区、片区、建筑物、楼层、房间数据进行增删改查&#xff0c;对房间属性数据进行批量修改。 3、档案及多类型附件管理:可对房产的…

对antd-vue输入框的二次封装,显示长度限制,兼容v-decorator和v-model

背景&#xff1a;antd组件中输入框长度限制没有显示&#xff0c;不能像elementUI一样&#xff0c;所以自己来封装实现 目的&#xff1a;对antd-vue输入框的二次封装&#xff0c;显示长度限制&#xff0c;兼容v-decorator和v-model 效果图&#xff1a; 代码&#xff1a; <…

JAVA方向程序设计PTA期末考试小测试

目录 1.方法重载 2.实例成员与类成员 3.static类成员 4.对象的组合 5. 对象的先上转型 6.引用类型&#xff08;数组&#xff09;参数传递 7.三角形类 8.机动车类补全代码 9.数组的引用与元素 10.求最大值 11.接口回调 12*.接口实现-Comparable 13.集体评分 14. 动…

@Windows server 2022安装使用(Workstation)

文章目录1.windows [iso下载](https://www.microsoft.com/zh-cn/evalcenter/evaluate-windows-server-2022)2.准备[workstation](https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html)&#xff08;个人测试&#xff09;3.安装windows server4.wi…

QT 使用第三方库QtXlsx操作Excel表

一直以来&#xff0c;都想学习一下C/C如何操作excel表&#xff0c;在网上调研了一下&#xff0c;觉得使用C/C去操作很麻烦&#xff0c;遂转向QT这边&#xff1b;QT有一个自带的类QAxObject&#xff0c;可以使用他去操作&#xff0c;但随着了解的深入&#xff0c;觉得他并不是很…

打造企业数智化管理新引擎,中国首份指标中台市场研究报告重磅发布!

12月15日&#xff0c;中国首份指标中台市场研究报告正式对外发布。该报告由专注数字化市场的研究咨询机构爱分析联合指标中台代表厂商 Kyligence 共同打造&#xff0c;内容聚焦指标管理和数据分析痛点&#xff0c;全面地梳理了指标中台概念、价值和应用落地方法论&#xff0c;并…

如何快乐地自学Python?阿里讲师用“四点”,说透快乐学习的方法

前言 由于我是自学Python&#xff0c;非科班出身&#xff0c;所以只能分享一些关于我的学习心得&#xff0c;如果有不对地方欢迎指正。 不过非科班出身虽然是一个痛点&#xff0c;但是在工作上&#xff0c;我其实不输给我其他同事&#xff0c;这点我倒是很有自信&#xff0c;…

活用 F12 开发者工具,测试效率原来可以提高这么多

推荐阅读&#xff1a; [内部资源] 想拿年薪30W的软件测试人员&#xff0c;这份资料必须领取~ Python自动化测试全栈性能测试全栈&#xff0c;挑战年薪40W 从功能测试进阶自动化测试&#xff0c;熬夜7天整理出这一份超全学习指南【附网盘资源】 什么是F12? F12开发者工具是…

HTTP详细介绍

HTTP 内容协商 什么是内容协商 在 HTTP 中&#xff0c;内容协商是一种用于在同一 URL 上提供资源的不同表示形式的机制。内容协商机制是指客户端和服务器端就响应的资源内容进行交涉&#xff0c;然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方…

FS32R294JCK0MJDT功能、FS32R294KCK0MJDT特点、FS32R294KAK0MJDT雷达微控制器

S32R294的特点与优势&#xff1a;内置雷达信号加速单元&#xff0c;简称SPT2.8&#xff0c;是专门服务于FMCW雷达的信号处理加速单元。同时&#xff0c;它是16纳米Power架构的处理器&#xff0c;与上一代处理器有非常好的软件兼容性&#xff0c;软件复用率高达80%&#xff1b;S…

【愚公系列】2022年12月 使用NSSM工具部署ELK三件套为Windows服务

文章目录前言一、使用NSSM工具部署ELK三件套为Windows服务1.安装ElasticSearch服务2.安装Kibana服务3.安装Logstash服务4.验证ELK服务前言 nssm是一个服务封装程序&#xff0c;它可以将普通exe程序封装成服务&#xff0c;实现开机自启动&#xff0c;同类型的工具还有微软自己的…