Linux进程——进程地址空间

前言:在讲完环境变量后,相信大家对Linux有更进一步的认识,而Linux进程概念到这也快接近尾声了,现在我们了解Linux进程中的地址空间!


在这里插入图片描述


本篇主要内容:
了解程序地址空间
理解进程地址空间
探究页表和虚拟地址空间

在这里插入图片描述


进程地址空间

  • 1. 程序地址空间
  • 2. 进程地址空间
  • 3. 什么是地址空间
  • 3. 地址空间的管理
  • 4. 页表
  • 5. 为什么要存在地址空间
  • 6. 总结拓展


1. 程序地址空间

我们在学习C语言的时候,大家都了解过这样的空间布局图

在这里插入图片描述
那么到底是不是这样排布的呢,我们来验证一下

    1 #include<stdio.h>2 #include<stdlib.h>3 4 int un_gval;5 int init_gval = 100;                         6                                      7 int main(int argc, char *argv[], char *env[])8  {                                            9      printf("code addr: %p\n", main);                   10      const char *str = "Hello, Linux!";                 11      printf("read only char addr: %p\n", str);          12      printf("init global value addr: %p\n", &init_gval);13      printf("uninit global value addr: %p\n", &un_gval);14                                     15      char *heap1=(char*)malloc(100);16      char *heap2=(char*)malloc(100);17      char *heap3=(char*)malloc(100);18      char *heap4=(char*)malloc(100);19                                        20      int a = 100;                      21                                        22      printf("heap1 addr: %p\n", heap1);23      printf("heap2 addr: %p\n", heap2);24      printf("heap3 addr: %p\n", heap3);25      printf("heap4 addr: %p\n", heap4); 26                                         27      printf("stack addr: %p\n", &str);  28      printf("stack addr: %p\n", &heap1);                                                                                                                                                       29       printf("stack addr: %p\n", &heap2);                                                                                                                                                30       printf("stack addr: %p\n", &heap3);31      printf("stack addr: %p\n", &heap4);                                                                                                                                                                  32      printf("a addr: %p\n",&a);  33      return 0;34  }

在这里插入图片描述


栈区中的数组和结构体

int num[10] ......&a[0]  &a[9]struct s
{int a; ......&s.aint b; ......&s.bint c; ......&s.c
}

在这里插入图片描述

注意:栈区是整体向下增长,局部想上使用的,就是地址最低处,依次往上放后面的元素


但是如果我们将代码更改还能运行过去嘛?

char *str = "Hello, Linux!"; 
*str = 'S';

在这里插入图片描述
显然我们是不能更改的,一更改就就运行不了了

注意:其实是因为字符常量区与代码区很接近,而编译器在编译时,字符常量区就是被编译到代码区的,代码又不可被写入,所以字符常量区也不可被修改

综上:

  • 栈区是整体向下增长,局部想上使用的,就是地址最低处,依次往上放后面的元素
  • 常量区的字符串不允许修改

但是这都是我们之前了解的知识,现在我们来重新了解地址,我们先来看这段代码

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

在这里插入图片描述
我们发现在开始时,输出出来的变量值和地址是一模一样的!
因为我们之前讲过子进程按照父进程为模版,父子并没有对变量进行进行任何修改

但是在达到一定条件之后,父子进程,输出地址是一致的,但是变量内容不一样!

但是相同的地址为什么会有不同的值?

  • 所以我们能得出结论,我们之前看到的地址,绝对不是物理地址,我们平时用到的地址,其实都是虚拟地址/线性地址!
  • 而虚拟地址就是进程地址空间的内容

2. 进程地址空间

我们现在来深入的了解一下为什么相同的的地址为什么会有不同的值?

首先引入一个概念:每一个进程运行之后,都会有一个进程地址空间的存在,在系统层面都要有自己的页表映射结构!
在这里插入图片描述

因此:当一个进程先修改后,它就不再指向原来那块物理空间,而是拥有一个新的物理空间!而页表左边的虚拟空间没有发生改变,所以相同的的地址为什么会有不同的值,是因为映射的物理空间不同!


3. 什么是地址空间

在讲什么是地址空间之前,我们先来讲一个故事,来方便理解!

一个拥有10亿美元身家的富豪,他有4个私生子,每个人都不知道彼此的存在,但是富豪对每个孩子都说,认真做好现在的事,在未来可以继承自己的10个亿家产。

在这里插入图片描述

但是在得到10个亿之前,他的几个孩子,在经济上遇到了问题,前三个都要找富豪要10w美金来解决麻烦,富豪觉得合情合理也就给了,但是它的第四个孩子直接找他要10个亿,富豪当然不能给他,然后讲明原因后给了他20w美金。因此他的所有孩子都可以得到10亿之内的经济资助,但是绝对拿不到10个亿。

在这里插入图片描述

在这个故事中:

  • 操作系统:富豪
  • 内存:10亿美金
  • 进程:私生子
  • 虚拟地址空间:继承10亿的大饼

虚拟地址空间并不是真实的地址


3. 地址空间的管理

富豪给每一个私生子都画了饼,他要把每个私生子都管理起来,也就是要把所有大饼管理起来。

因此:地址空间也要被OS管理起来!!每一个进程都要有地址空间,系统中,一定要对地址空间做管理!!

而操作系统管理地址空间,一定是“先描述,在组织”!地址空间最终一定是一个内核的数据结构对象,
就是一个内核结构体!

在这里插入图片描述
而我们观察进程地址空间,发现里面是一堆的地址划分。
在Linux中,这个描述虚拟地址空间的东西叫做:

struct mm _struct
{long code_start;long code_end;long data_start;long data_end;long heap_start;long heap end; //brklong stack _start;long stack _end;......
}

在这里插入图片描述
而该结构体的大小会被初始化成4gb,线性编程范围从全0到全F,然后把线性范围拆分成细小的范围,这就是地址空间


4. 页表

在上面我们了解到了页表,页表的映射关系中左侧表示虚拟地址,右侧表示物理地址,但是除了这两个其实在页表的映射关系中还存在一个标记字段——访问权限字段

在这里插入图片描述
讲到这里我们再回到字符常量区那里。

char *str = "Hello, Linux!"; 
*str = 'S';

此时我们就可以解释通字符常量区为什么不能修改:

  • 字符常量区在经过页表映射时,访问权限字段只设置成只读的,所以在写入时,页表直接将我们拦住,不让我们访问,所以字符常量区不能修改,代码区也是如此!

所以页表可以进行安全评估,有效的进行进程访问内存的安全检查


在除去上面提到的东西以外,页表还可以通过二进制衡量能存中有没有内容,是否分配地址

在这里插入图片描述
当我们有个虚拟地址要被访问了,但是它并没有被分配空间,更不会有内容,那该则么办呢?
在这里插入图片描述

其实在这个时候操作系统会将你的这个访问暂停,然后进行一下操作:

  • 操作系统会将你的可执行程序重新开辟空间
  • 把对应可执行程序需要执行的这个虚拟地址对应的代码加载到内存里
  • 把对应的虚拟地址填充到页表
  • 把标志位改为1,代表已经分配地址,且内容已经填充
  • 将暂停的代码继续访问

操作过程也称为缺页中断

而我们操作系统在进行这些工作时,是在进行内存管理, 而进程管理和内存管理因为有了地址空间的存在 ,实现了在操作系统层面上的模块的解耦!


5. 为什么要存在地址空间

到了这里我想大家也都了解得差不多了,为什么要存在地址空间,原因有很多

一、 让无序便有序

  • 让进程以统一的视角看待内存
  • 在页表层映射时会将不同的数据类型进行划分使得映射到物理内存后是比较有序的一种状态!
  • 所以任意一个进程,可以通过地址空间+页表可以将乱序的内存数据,变成有序,分门别类的规划好!

二、存在虚拟地址空间,可以有效的进行进程访问内存的安全检查

三、将进程管理和内存管理进行解耦

四、保证进程的独立性

通过页表让进程虽然虚拟地址一样但是映射到不同的物理内存处,从而实现进程的独立性

6. 总结拓展

拓展:
在mm_struct中还会存在一个struct vm_area_struct的结构 ,它能划分出一个start,一个end。如果我们还想继续划分就会有多个struct vm_area_struct的结构,然后他们会构成一个线性划分的链表结构。

struct vm_area_struct
{struct mm_struct * vm_mm;unsigned long vm_start;unsigned long vm_end;......
}

到这里我们的进程地址空间也接近尾声了,地址空间让进程管理和内存管理互不干涉,起到了很大作用。结束进程地址空间,我们的Linux进程概念到这里也结束了,后面我将带大家走进进程控制。

谢谢大家支持本篇到这里就结束了

在这里插入图片描述

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

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

相关文章

matlab使用教程(71)—控制坐标区布局

1.与位置相关的属性和函数 有几个属性和函数可用于获取和设置坐标区的大小与位置。下表摘要显示了这些属性和函数。 函数或属性描述 OuterPosition 属性 使用此属性可以查询或更改坐标区的外边界&#xff0c;包括标题、标签和边距。要更改外边界&#xff0c;请将此属性指定为…

MySQL、JDBC复盘及规划

数据库仍有习题尚未做完&#xff0c;策略从一天做完改为每天5到10题&#xff0c;以此达到掌握和复习的效果&#xff0c;JDBC的六部仍需每天练习&#xff0c;从明天开始正式进行JavaWeb的学习&#xff0c;预计持续到七月中旬&#xff0c;还会完成一个书城项目&#xff0c;六月底…

Vue 快速入门:Vue初级

语法规则 前端渲染 渲染有几种方式&#xff1a;原生js、js模板、Vue模板语法 原生js 使用字符串拼接 js模板语法 Vue.js 模板语法概述 Vue.js 是一个用于构建用户界面的渐进式框架&#xff0c;其模板语法非常灵活和直观。Vue 的模板语法基于 HTML&#xff0c;可以通过指令…

Java为什么会成为现在主流的编程语言

Java为什么会成为现在的主流语言 前言一、Java语言概述Java是什么为什么大多数人会选择从事Java为什么从事Java的工作者数量从年递减 二、Java语言的特点简单性面向对象分布式&#xff08;微服务&#xff09;健壮性安全性体系结构中立可移植性解释型高性能多线程动态性 三、Jav…

UDP多对多组播通信

广播和多播仅应用于UDP。TCP是一个面向连接的协议&#xff0c;TCP一定是点对点的&#xff0c;一点是两个主机来建立连接的&#xff0c;TCP肯定是单播。只有UDP才会使用广播和组播。 如下示例实现一个UDP多对多的组播通信&#xff0c;进程中有收、发两个线程&#xff0c;分别表…

6款电脑精选工具软件推荐!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 1.IP地址查看工具——纯真ip数据库 纯真IP数据库是一个易于操作的IP地址查询工具&#xff0c;它允许用户通过输入IP地址来查询其对应的地理位置…

Django创建网站的地基

相关文档 1、为新网站创建一个文件夹&#xff08;这里是&#xff1a;locallibrary&#xff09; D:\django>mkdir locallibraryD:\django>cd locallibraryD:\django\locallibrary>dirVolume in drive D is 新加卷Volume Serial Number is B68C-03F7Directory of D:\dj…

【Uniapp】简易封装提示框showToast/showModal

组件 // 封装提示框 export const showModal (content, showCancel false, title "提示") > {return new Promise((resolve, reject) > {uni.showModal({title: title,content: content,showCancel: showCancel,success: (res) > {resolve(res);},fail:…

结合多模态 AI 谷歌展示 AR 眼镜原型机;Meta 被曝开发带摄像头的 AI 耳机丨 RTE 开发者日报 Vol.204

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」&#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

如何修改android 项目显示的app名

修改vlaues下的string.xml文件 修改这个标签中的内容就行

国产银河麒麟V10SP1系统安装Qt和MySql步骤

安装软件&#xff1a;准备好Kylin-Desktop-V10-SP1-Release-hwe-2107-x86_64.iso和qt-opensource-linux-x64-5.14.2.run 安装步骤&#xff1a; 1、VMWare软件中新建一个虚拟机并安装Kylin-Desktop-V10-SP1-Release操作系统&#xff0c;安装时候输入密码的地方记得要用英文&am…

“网络安全新纪元:等保2.0的详细解读与实践”

网络安全等级保护基本要求》&#xff08;等保2.0&#xff09;于2019年6月发布&#xff0c;是我国网络安全等级保护制度的一项重要标准。等保2.0主要针对关键信息基础设施的网络安全保护&#xff0c;对数据安全和个人信息保护提出了更高的要求。本文将对等保2.0进行详细解读&…

动态路由实验新手入门:快速掌握核心知识点

大家好&#xff0c;这里是G-LAB IT实验室。今天带大家学习一下华为动态路由实验配置&#xff0c;新手入门&#xff0c;快速掌握核心知识点&#xff01; 01、实验拓扑 02、实验需求 1.根据拓扑运行对应的路由协议 2.每个路由器都有自己的环回口&#xff0c;宣告的区域不限制 …

IDEA不能创建新项目和新模块

问题&#xff1a; IDEA不管是创建新项目还是新模块都创建不成功&#xff0c;会报如下图错误 解决方案&#xff1a; 在电脑设置里搜索 “防火墙和网络保护” &#xff0c;打开如下图所示 找到你所安装的IDEA&#xff0c;更改设置&#xff0c;选中IDEA 最后&#xff0c;确定&am…

香港优才计划避坑指南及过来人建议,这6种行为会毁了你的香港身份!

香港优才计划是一项香港人才引进政策&#xff0c;如果你想真正落户香港&#xff0c;那么就需要了解清楚香港优才从申请到永居的整个流程&#xff0c;并且要注意维护好香港身份。 如果操作不当&#xff0c;可能会中断你来之不易的香港身份。 本文总结了香港优才整个流程中&…

nmap端口扫描工具——Win10

Nmap安装流程&#xff1a; Nmap官网链接&#xff1a;Download the Free Nmap Security Scanner for Linux/Mac/Windows Nmap参考文档链接&#xff1a;https://nmap.org/book/toc.html Nmap使用流程&#xff1a; Nmap软件主页面&#xff1a; 中文版&#xff1a; nmap -T4 -…

Prosys OPC UA Simulation Server工程文件备份方法

Prosys OPC UA Simulation Server是一款免费的OPC UA服务器仿真软件&#xff0c;具体的使用和下载参考官网&#xff1a; Prosys OPC - OPC UA Simulation Server Downloads 他的免费版本不提供工程文件的备份、导入导出功能&#xff0c;每次退出时保存。如果需要工程备份&a…

IPsec VPN简介

什么是IPsec&#xff1f; IPsec&#xff08;Internet Protocol Security&#xff09;是为IP网络提供安全性的协议和服务的集合&#xff0c;它是VPN&#xff08;Virtual Private Network&#xff0c;虚拟专用网&#xff09;中常用的一种技术。其实就是一种协议簇&#xff08;类…

揭秘SmartEDA魅力:为何众多学校青睐这款电路仿真软件?

在当今数字化、信息化的教育时代&#xff0c;电子电路仿真软件已成为电子学教学不可或缺的重要工具。其中&#xff0c;SmartEDA电路仿真软件以其强大的功能、用户友好的界面以及丰富的教育资源&#xff0c;赢得了众多学校的青睐。那么&#xff0c;究竟是什么原因让SmartEDA成为…

如何在阿里云申请免费SSL证书(三个月有效)

SSL证书主要用于建立Web服务器和客户端间可信的HTTPS协议加密链接&#xff0c;以防止数据在传输过程中被篡改&#xff0c;避免信息泄露。阿里云提供了多种品牌和类型的SSL证书&#xff0c;以满足不同用户的需求。您可以根据自己的预算、域名类型以及网站类型&#xff0c;选择购…