【Linux系统化学习】进程地址空间 | 虚拟地址和物理地址的关系

news2024/11/26 0:26:05

=========================================================================

个人主页点击直达:小白不是程序媛

Linux专栏:Linux系统化学习

代码仓库:Gitee

=========================================================================

目录

虚拟地址和物理地址

页表

进程地址空间

进程地址空间存在的意义


虚拟地址和物理地址

我们在学习C/C++的时候肯定都见过下面这张有关于内存分布的图片:

在来段代码理解感受下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 //未初始化常量
  4 int un_gval;
  5 //初始化常量
  6 int init_gval=100;
  7 int main()
  8 {
  9     //代码区地址
 10     printf("code addr: %p\n",main);
 11     //字符常量
 12    const char *str="hellolinux!";
 13 
 14     //常量区地址
 15     printf("read only char addr : %p\n",str);
 16     //已初始化全局数据区
 17     printf("init global value addr: %p\n",&init_gval);
 18     //未初始化全局数据区
 19     printf("uninit global value addr: %p\n",&un_gval);
 20 
 21     char *heap1=(char*)malloc(100);
 22     char *heap2=(char*)malloc(100);
 23     char *heap3=(char*)malloc(100);
 24     char *heap4=(char*)malloc(100);
 25     static int a=0;
 26     printf("heap1 addr:%p\n",heap1);                                                                                                                                                                    
 27     printf("heap2 addr:%p\n",heap2);
 28     printf("heap3 addr:%p\n",heap3);
 29     printf("heap4 addr:%p\n",heap4);
 30 
 31     printf("stack addr:%p\n",&str);
 32     printf("stack addr:%p\n",&heap1);
 33     printf("stack addr:%p\n",&heap2);
 34     printf("stack addr:%p\n",&heap3);
 35     printf("stack addr:%p\n",&heap4);
 36     printf("a addr:%p\n",&a);
 37 
 38     return 0;
 39 }

通过上面这段代码,我们好像不仅验证了上面的空间分布图片,而且还发现了栈区和堆区相向而生的内存开辟特点。

上两篇文章我们介绍了命令行参数和环境变量,其实这两个就储存在栈区之上的空间,来段代码验证下:

    1 #include<stdio.h>
W>  2 int main(int argc , char *argv[], char *env[])
    3 {
    4     int i=0;
    5     printf("i addr:%p\n",&i);                              
    6     for(;argv[i];i++)
    7     {
    8         printf("argv[%d]:%p\n",i,argv[i]);
    9     }
   10     for(i=0;env[i];i++)
   11     {
   12         printf("env[%d]:%p\n",i,env[i]);
   13     }
   14     return 0;
   15 }
  ~

 

验证完这些,话说回来其实我们之前学的对内存的概念就上面所介绍的内容其实都不是真正意义上的内存是虚拟内存,不是我们真正意义上的内存物理地址。

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>                                                                                                                                                                     
  4 int g_val = 100;
  5 
  6 int main()
  7 {
  8     pid_t id = fork();
  9     if(id == 0)
 10     {
 11         //child
 12         int cnt = 5;
 13         while(1)
 14         {
 15             printf("child, Pid: %d, Ppid: %d, g_val: %d, &g_val=%p\n", getpid(), getppid(), g_val, &g_val);
 16             sleep(1);
 17             if(cnt == 0)
 18             {
 19                 g_val=200;
 20                printf("child change g_val: 100->200\n");
 21             }
 22             cnt--;
 23         }
 24     }
 25     else
 26     {
 27         //father
 28         while(1)
 29         {
 30             printf("father, Pid: %d, Ppid: %d, g_val: %d, &g_val=%p\n", getpid(), getppid(), g_val, &g_val);
 31             sleep(1);
 32         }
 33     }
 34 
 35     sleep(100);
 36     return 0;
 37 }

我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:

  • 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量 
  • 但地址值是一样的,说明,该地址绝对不是物理地址!
  • 在Linux地址下,这种地址叫做 虚拟地址
  • 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理OS必须负责将 虚拟地址 转化成 物理地址 

我们再将同一个可执行程序同时运行也会发现两个进程的获取到的地址竟然也是一样的。

 话又说回来,我们的可执行程序运行时肯定会加载到内存中,因此虚拟地址和物理地址一定有关联,这个关联就是页表


页表

页表就是将虚拟地址和物理地址联系起来的一种模型,其中还包括变量是否可以被修改,进程的状态等诸多信息。

上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!

每个进程的页表的物理地址存在与CPU中CR3的寄存器中


进程地址空间

进程地址空间其实我们可以使用内存大小的一个范围,以我们32位总线的机器为例:它的范围为0000 0000 -> ffff ffff ,也就是0到2^32次方(我们所谓的4GB)。模拟其物理空间大小进行区域划分后形成栈区、堆区等等的虚拟地址,操作系统通过结构体将每个区域的起始和结束统计记录起来,进程的PCB中含有指向这个结构体的指针。

因此,每当新的进程创建时会形成对应的PCB,PCB和PCB中的虚拟地址结构体指针和页表关联起来,对真正上的物理地址进行使用。 


进程地址空间存在的意义

  • 让进程以统一的视角看待内存,所以任意一个进程,可以通过地址空间和页表可以将乱序的内存数据,变成有序,分门别类的规划好
  • 存在虚拟地址空间,可以有效的进行进程访问内存的安全检查
  • 将进程管理和内存管理进行解耦,通过页表让进程映射到不同的物理内存处,从而实现进程的独立性。

今天对Linux下进程地址空间的介绍分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法。您三连的支持就是我前进的动力,感谢大家的支持!!!

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

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

相关文章

Flameshot的安装、配置及使用

概要&#xff1a;本篇主要介绍在Ubuntu22.04环境下&#xff0c;截图软件Flameshot的安装、配置及使用。 一、安装 推荐命令行安装 sudo apt install flameshot 二、修改gdm3配置文件 这一步是为了解决截图时没有光标的问题&#xff0c;解决方法我是从这里学到的解决flam…

【Linux】如何清空某个文件的内容

cat /dev/null > file1 清空某个文件的内容使用cat /dev/null > file1&#xff0c;它将 /dev/null 的内容&#xff08;空内容&#xff09;重定向到 file1。 如下所示&#xff0c;file1文件里的内容被清空。 错误写法 错误写法是&#xff1a;cat file1 > /dev/null&…

LeetCode Hot100 131.分割回文串

题目&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 方法&#xff1a;灵神-子集型回溯 假设每对相邻字符之间有个逗号&#xff0c;那么就看…

高效的多维空间点索引算法——GeoHash

一、Geohash 算法简介 GeoHash是空间索引的一种方式&#xff0c;其基本原理是将地球理解为一个二维平面&#xff0c;通过把二维的空间经纬度数据编码为一个字符串&#xff0c;可以把平面递归分解成更小的子块&#xff0c;每个子块在一定经纬度范围内拥有相同的编码。以GeoHash方…

leetcode面试经典150题——35 螺旋矩阵

题目&#xff1a; 螺旋矩阵 描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 提示&…

P4 Qt如何添加qss样式表文件和添加图片资源

目录 前言 01 添加图片资源文件 02 添加qss文件 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Qt基础_ChenPi的博客-CSDN博客》✨✨✨ &#x1f33a;本篇简介 &#xff1a;这一章…

【STM32】蓝牙氛围灯

Docs 一、项目搭建和开发流程 一、项目需求和产品定义 1.需求梳理和产品定义 一般由甲方公司提出&#xff0c;或由本公司市场部提出 需求的重点是&#xff1a;这个产品究竟应该做成什么样&#xff1f;有哪些功能&#xff1f;具体要求和参数怎样&#xff1f;此外还要考虑售价…

Advanced Renamer

Advanced Renamer 安装链接 1.前后添加字符 2.字符转数字&#xff0c;编号整体加减

混合预编码(Hybrid Precoding)的全连接结构与子连接结构

A Survey on Hybrid Beamforming Techniques in 5G: Architecture and System Model Perspectives 全连接结构的混合预编码 子连接结构的混合预编码 Alternating Minimization Algorithms for HybridPrecoding in Millimeter Wave MIMO Systems

Rust测试字符串的移动,Move

代码创建了一个结构体&#xff0c;结构体有test1 字符串&#xff0c;还有指向字符串的指针。一共创建了两个。 然后我们使用swap 函数 交换两个结构体内存的内容。 最后如上图。相同的地址&#xff0c;变成了另外结构体的内容。注意看指针部分&#xff0c;还是指向原来的地址…

HttpComponents: 概述

文章目录 1. 概述2. 生态位 1. 概述 早期的Java想要实现HTTP客户端需要借助URL/URLConnection或者自己手动从Socket开始编码&#xff0c;需要处理大量HTTP协议的具体细节&#xff0c;不但繁琐还容易出错。 Apache Commons HttpClient的诞生就是为了解决这个问题&#xff0c;它…

【C++】仿函数在模板中的应用——【默认模板实参】详解(n)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.引入&#xff1a;查看(容器)文档时常…

UE4 材质实现Glitch效果

材质实现Glitch效果 UE4 材质实现Glitch效果预览1预览2 UE4 材质实现Glitch效果 预览1 添加材质函数&#xff1a; MF_RandomNoise 添加材质&#xff1a; 预览2 添加材质函数MF_CustomPanner&#xff1a; 添加材质函数&#xff1a;MF_Glitch 材质添加&#xff1a; 下面用…

免费的网页数据抓取工具有哪些?【2024附下载链接】

在网络上&#xff0c;有许多网页数据抓取工具可供选择。本文将探讨其如何全网采集数据并支持指定网站抓取。我们将比较不同的数据采集工具&#xff0c;帮助您找到最适合您需求的工具。 网页数据抓取工具种类 在选择网页数据抓取工具之前&#xff0c;让我们先了解一下这些工具…

基于单片机音乐盒仿真仿真系统设计

**单片机设计介绍&#xff0c;基于单片机音乐盒仿真仿真系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的音乐盒仿真仿真系统是一种基于嵌入式系统技术的设计方案&#xff0c;用于模拟传统的音乐盒功能。它通…

pyside/qt03——人机协同的编程教学—直接面向chatGPT实战开发(做中学,事上练)

先大概有个草图框架&#xff0c;一点点丰富 我纠结好久&#xff0c;直接用Python写UI代码 还是用designer做UI 再转Python呢&#xff0c; 因为不管怎么样都要转成Python代码&#xff0c; 想了想还是学一下designer吧&#xff0c;有个中介&#xff0c;有直观理解。 直接这样也可…

RHEL网络服务器

目录 1.时间同步的重要性 2.配置时间服务器 &#xff08;1&#xff09;指定所使用的上层时间服务器。 (2&#xff09;指定允许访问的客户端 (3&#xff09;把local stratum 前的注释符#去掉。 3.配置chrony客户端 &#xff08;1&#xff09;修改pool那行,指定要从哪台时间…

nodejs+vue+微信小程序+python+PHP的游戏测评网站设计与实现-计算机毕业设计推荐

通过软件的需求分析已经获得了系统的基本功能需求&#xff0c;根据需求&#xff0c;将游戏测评网站功能模块主要分为管理员模块。管理员添加个人中心、管理员管理、基础数据管理、公告管理、用户管理、游戏管理、游戏测评管理、游戏攻略管理、轮播图信息等操作。  随着时代的…

Kafka在微服务架构中的应用:实现高效通信与数据流动

微服务架构的兴起带来了分布式系统的复杂性&#xff0c;而Kafka作为一款强大的分布式消息系统&#xff0c;为微服务之间的通信和数据流动提供了理想的解决方案。本文将深入探讨Kafka在微服务架构中的应用&#xff0c;并通过丰富的示例代码&#xff0c;帮助大家更全面地理解和应…

Windows 12 和 AI 计算机

据商业时报消息 &#xff0c;微软计划于 2024 年 6 月发布Windows 12。 新版本的操作系统将伴随集成人工智能。 该数据基于广达首席执行官林百里和宏基陈杰森在中国台北医疗科技展上的发言。 虽然这篇文章没有直接引用微软高管的话&#xff0c;但它是根据他们的评论得出的结…