【Linux】深挖进程地址空间

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:熟悉【Linux】进程地址空间

> 毒鸡汤:也许有一天,你发觉日子特别的艰难,那可能是这次的收获特别的巨大。

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言

        学习每一个语言都跟地址扯不开关系,这也是学习每一种语言的必修课,学习好地址空间对语言的掌握熟练度就是质的飞越,我们学习代码知识只是语言的表面,像地址空间就比较深层,有点抽象,不好理解,基于这种情况博主给大家带来【Linux】深挖进程地址空间。

⭐主体

我们从以下学习【Linux】深挖进程地址空间😋😋。

简单来讲就是是什么,为什么,怎么做😜😜。

🌙什么是进程地址空间

再次回顾 C/C++ 学习地址空间时候:

地址空间是什么?是内存么?我们举个栗子:

代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>int g_val = 100;
int main()
{pid_t id = fork();assert(id >= 0);if (id == 0) {while (1){printf("我是子进程,我的id是:%d,我的父进程是:%d,g_val:%d,&g_val:%p\n", getpid(), getppid(), g_val, &g_val);sleep(1);g_val = 200;}}else{while (1){printf("我是父进程,我的id是:%d,我的父进程是:%d, g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);sleep(1);}}return 0;
}

运行结果:

通过上图可以发现子进程的g_val修改成了200,但是父进程的g_val始终未改变的。

  • 我们的fork调用之后创建了一个子进程,父子进程的代码和数据共享,而进程是具有独立性的
  • 所以改变子进程的g_val的值并不会影响父进程的g_val,这是得益于fork函数采用了写实拷贝的方法实现的

最大的问题是父子进程的地址相同,对应的g_val值竟然不一样?同一块空间有两个不同的值??

  • 这块空间绝不是物理地址(内存),因为物理地址(内存)对应的内容肯定是唯一的!!
  • 不可能会出现同一个变量的地址读取出两个不同的值。

这里的地址实际上是虚拟地址(线性地址),Linux也有可能叫做逻辑地址。

虚拟空间:所以对于我们而言,直接使用虚拟地址,操作系统再从虚拟地址到页表加载到内存,在通过页表映射,找到对应的物理内存。也就是说,操作系统自动完成。

采用图解的方式:

  • 父进程和子进程都有自己的独立的进程地址空间,且都有自己的页表结构。
  • 子进程由父进程创建,所以子进程的地址空间是从父进程拷贝而来,刚开始的g_val经过映射指向同一个物理内存,所以刚开始看到的都是100。

        后来子进程修改了自己地址空间的g_val的值,当操作系统通过页表映射发现g_val的值是共享的,但是我们知道进程具有独立性,所以操作系统为了保证进程的独立性,当子进程或者父进程任何一方尝试对共享数据进行写入,那么操作系统会在物理内存上重新开辟一块新的内存空间,拷贝数据,然后在修改映射关系,不再指向老的变量,在整个修改的过程中,和父子进程的虚拟地址没有任何关系,只是底层经过页表映射到不同的区域,所以我们看到了地址是一样的,但是内容却是不一样的,这就是现象的由来!

如何理解线性地址?

        以32位计算机为例,我们有32根地址线,每根地址线对应的数据只有0 1信号,那么32根地址线就有2^32中排列组合,就有2^32个地址,我们的CPU在运算完某些数据之后,会进行寻址找到一段地址空间将其存放在内存中,内存地址中最小的单位为字节,那么2^32个地址占据2^32个字节空间,换算出来总的地址空间大小就是4GB!!因为我们的地址是按照字节号大小依次递增的,所以我们就认为地址空间是一个线性结构。

🌙为什么要虚拟地址空间

  • 进程地址空间保证了数据的安全性。

        每个进程都有进程地址空间,所有的进程都要通过页表映射到物理内存,如果进程直接访问物理内存,万一进程越界非法访问、非法读写时,页表就可以进行拦截,而且直接访问物理内存对于账号信息是非常不安全的,所以保证了内存数据的安全性。

  • 地址空间的存在,可以更方便的进行进程和进程的数据代码的解耦,保证了进程独立性的特征

        对于进程而言,都有独立的地址空间及页表,通过页表映射到不同的物理内存上,所以一个进程数据的改变不会影响到另一个进程,保证了进程的独立性,而对于上面我们所说的父进程和子进程而言,子进程的地址空间从父进程拷贝,页表都指向同一块物理内存,但是即使此时的数据是共享的,在修改数据的时候也会发生我们所说的写时拷贝,保证了进程的独立性

  • 让进程以统一的视角,看待进程对应的代码和数据各个区域,方便编译器也以统一的视角来进行编译代码。

        可执行程序被编译器编译的时候每个代码和数据在内存中已经有虚拟地址了(在磁盘上称为逻辑地址),也就是说,地址空间对于操作系统和编译器都是遵守的。所以当程序被加载到内存成为进程后,每个变量/函数都具备了物理地址。

所以我们现在有两套地址:

  1. 标识物理内存中代码和数据的地址
  2. 在程序内部互相跳转的时候的虚拟地址

        加载完成之后,代码的各个区域的地址已经知道。进程被调度时,CPU拿到虚拟地址,经过地址空间查页表通过映射,进行访问查到物理地址往后执行。也就是CPU通过了虚拟地址——页表映射——物理地址执行。也就是在整个CPU运行过程中,CPU并没有见到物理地址,用的都是虚拟地址。

        另外,对于磁盘内可执行程序编译好,这个可执行程序的地址不叫虚拟地址,是逻辑地址。但是对于Linux而言,虚拟地址、线性地址、逻辑地址都是一样的。

🌙虚拟地址与物理地址如何联系

        fork在返回时,父子进程都已经创建好了,这两个进程是独立的,是不是就会return两次?返回的本质是不是写入?谁先return谁就先进行写实拷贝,同一块地址是子进程继承父进程的虚拟地址,return返回写入后,它们就映射到不同的物理空间上了。

   🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

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

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

相关文章

vue连接本地服务器

vue 连接本地服务器做后端。 后端服务 使用springboot新建一个基于restful的接口&#xff0c;访问如下的地址&#xff0c;返回值。 vue构建 新建一个vue项目&#xff0c;安装访问服务器的插件。 npm install axios vue-axios --save 修改main.js使用axios&#xff0c;最终…

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生

测试员可以先在大厂镀金&#xff0c;以后去中小厂毫无压力&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大厂出来…

svg学习

概念 svg 可缩放矢量图形 svg 使用xml格式定义图像 svg 形状 矩形 <rect> <?xml version"1.0" standalone"no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd&q…

【事故总结】Mybatis-Wrapper导致的生产事故

近期遭遇了一次生产环境的严重告警&#xff0c;涉及慢接口和CPU过载。经过排查&#xff0c;发现问题根源在于一段使用MyBatis的查询代码。当传入空列表作为查询条件时&#xff0c;MyBatis会忽略该条件&#xff0c;导致全表扫描&#xff0c;进而引发系统资源耗尽和频繁的Full GC…

《别让猴子跳回背上》——管理者的时间管理

讲时间管理的书很多&#xff0c;但这本是专门讲给管理者的时间管理。 在职场中&#xff0c;许多管理者都会碰到工作计划执行不下去、组织目标难于实现的问题&#xff0c;搭进了自己所有可以支配的时间&#xff0c;仍旧是焦头烂额&#xff0c;顾此失彼&#xff1b;而下属则因为…

PowerShell Instal 一键部署TeamCity

前言 TeamCity 是一个通用的 CI/CD 软件平台,可实现灵活的工作流程、协作和开发实践。允许在您的 DevOps 流程中成功实现持续集成、持续交付和持续部署。 系统支持 Centos7,8,9/Redhat7,8,9及复刻系列系统支持 Windows 10,11,2012,2016,2019,2022高版本建议使用9系列系统…

LabVIEW各版本安装指南

链接地址如下&#xff1a; https://pan.baidu.com/s/1NF9hY03bApwwpI-WVHGlZg?pwd0531 1.鼠标右击【LabVIEW2023】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 LabVIEW2023】。 2.打开解压后的文件夹&#xff0c;双击打开【Setup】文件…

C语言 volatile关键字

volatile关键字介绍 volatile 是一个关键字&#xff0c;用于修饰变量&#xff0c;表示该变量是易变的&#xff0c;即可能在任何时候被意外地改变。在多线程编程中&#xff0c;当多个线程同时访问同一个变量时&#xff0c;由于线程之间的交互和优化&#xff0c;可能会导致变量的…

【挑战全网最易懂】深度强化学习 --- 零基础指南

深度强化学习介绍、概念 强化学习介绍离散场景&#xff0c;使用行为价值方法连续场景&#xff0c;使用概率分布方法实时反馈连续场景&#xff1a;使用概率分布 行为价值方法 强化学习六要素设计奖励函数设计评论家策略学习与优化 算法路径深度 Q 网络 DQN演员-评论家算法&…

echarts常见的一些大屏示意图及配置项【好看】

双立体柱状图 示意图&#xff1a; 配置&#xff1a; initData() {let sideData [220, 182, 191, 234, 290, 330]let sideData1 [100, 110, 120, 134, 190, 230]let nameList [结算能力数, 结算金额]let yAxisData [(金额/亿元), (能力数/个)]let xData [1, 2, 3, 4, 5…

Anolis安装Jdk保姆级教学

前言 欢迎来到本博客&#xff0c;我们将带领你完成在Anolis操作系统上安装Java Development Kit&#xff08;JDK&#xff09;的详细过程。Anolis操作系统是一款基于Linux的轻量级操作系统&#xff0c;专为容器和云原生应用而设计。在Anolis上安装JDK将为你提供一个稳定、高效的…

1万亿元国债支持水利、应急行业,钡铼智能终端积极助力提升防灾抗洪建设需求

10月24日&#xff0c;十四届全国人大常委会第六次会议审议通过了国务院关于增加发行国债支持灾后恢复重建和提升防灾减灾救灾能力的议案。为贯彻落实中共中央政治局常委会会议精神&#xff0c;以强有力的资金保障有关工作落实&#xff0c;中央财政将在今年四季度增发2023年国债…