Linux进程地址空间——上篇

news2025/2/25 14:13:36

目录 

一. 前言:

二.进程地址空间

1.通过一个例子去初步的了解进程地址空间:

        使用VS写了一段代码:

        在Linux中使用vim编辑器写类似的代码:

 结果解析:

2.什么是进程地址空间?

举个例子大家就明白了画饼的意义:

如何画大饼?

3.详谈进程地址空间: 

 ​编辑

 进程地址空间的结构体源码:

 


一. 前言:

       当我们在学习C语言/C++的过程中,想必经常会在书中见过上面这副图吧,我想问问,大家眼中的这幅图代表着什么?

        其实这是个地址空间,从低到高,从下而上,有各个区域,例如:代码区、堆区、栈区、静态区等,有的同学会说:“这不就是计算机中的内存(物理)地址空间吗?我们写的代码数据被运行后都会加载进内存”。其实这块地址空间并不是内存,而是进程的虚拟地址空间,是每个进程专属拥有的空间!

二.进程地址空间

1.通过一个例子去初步的了解进程地址空间:

        使用VS写了一段代码:

 在该程序中,在局部中修改全局变量的值,并打印修改前后的变化。

        在Linux中使用vim编辑器写类似的代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int gloval=100;    //全局变量


int main(){
    pid_t id=fork();    //创建子进程
    if(id<0){
        printf("create process perror!");
        return -1;
            }

    //子进程执行流代码:
    else if(id==0){
        int cnt=0;
        while(1){
            printf("我是子进程,pid:%d ppid:%d,gloval:%d,gloval地址:%p\n",           
                              getpid(),getppid(), gloval,  &gloval);
            cnt++;
            if(cnt==10) gloval=300;
                }
            }

    //父进程执行流代码
    else{
        while(1){
          printf("我是父进程 , pid: %d , ppid: %d , gloval: %d , gloval地址: 
                 %p\n",getpid(),getppid(),gloval,&gloval);
          sleep(2); 
        }
    return 0;
    }

 运行结果:

 结果解析:

       1. 我们从代码中得知父进程的gloval为100,地址0x60105c,子进程的gloval和地址与父进程的一样,没问题,因为gloval是全局变量

        2.因为代码中用了fork函数(创建子进程,表示当前该程序中有两个执行流),父子进程各自执行各自的while循环代码,但是从绿框那部分的显示结果中可以发现:子进程在循环中对全局变量gloval进行修改,变为了300没问题,但是纵观父进程的执行结果来看,gloval却还是100,gloval既然是全局变量,那为什么父子进程在读取同一个地址/变量的过程中,双方怎么会出现不同的结果呢?

        按理说,gloval作为全局变量,子进程对其进行修改,那么父进程读取的就应该是gloval被修改过之后的值了(注gloval的地址从始至终没有变过,所以肯定不是变量的问题) 。

 那么根据这个结果,我们可以得出一个结论:

        之前我们在C/C++学习的过程中,从屏幕中打印出来的地址,绝对不是对应的物理地址,而叫做虚拟地址,那么上面的那个图所表示的也根本不是内存地址空间,而叫做虚拟地址空间。

        知识解析:任何我们学过的语言,C/C++/Java/Python等,从代码中获取变量/指针/函数地址都绝对不会是物理地址。虚拟地址是由操作系统提供的,既然是虚拟地址,那么一定有某种途径会将虚拟地址转化为物理地址,因为程序在被启动时数据和代码必须被加载到物理内存中,那么在内存中,代码中的各种变量和函数也就有了自己的物理地址——这是冯诺依曼体系所规定的,所以在加载到内存之前,肯定是将虚拟地址转换为物理地址,这里的转化工作由操作系统完成。

        


        

2.什么是进程地址空间?

        进程地址空间——又叫虚拟地址空间,就是从进程的视角去看地址空间,是进程运行时就用到的代码数据虚拟地址的集合。操作系统会给每个进程都创建一个独立的虚拟地址空间,而虚拟地址空间的大小与内存空间的大小相同(一般为4GB)。那为什么虚拟地址空间会和内存一样大呢?操作系统会给进程画大饼,让进程以为它可以使用整个内存的资源空间。

        每个进程总是认为自己是独占内存资源的,但其实只是操作系统画给进程的大饼,让进程相信自己是独占内存资源的,这样可以提升进程的使用效率。

举个例子大家就明白了画饼的意义:

        一个外国的富豪拥有十个亿的身价,这个富豪没有结婚已经年迈老矣,但在外面有3个私生子,其中有两个儿子被父亲安排到他手底下的公司去锻炼,大儿子是麾下某个工厂的老板,二儿子是金融公司的总经理,三儿子年龄比较小在大学读书。这三个私生子彼此并不知道其他两个的存在,富豪对自己的大儿子子勉励说:“你要积极上进,好好努力,为自己的未来做出业绩,等老爸以后走了,我的十亿遗产就全是你的了!” ;对二儿子也勉励说:“你要多向公司有经验的前辈汲取经验,把握好每一个项目的分寸,冷静思考,等老爸以后走了,公司就靠你了,我这几十年所获得的一切也就是你的了!”;对三儿子也勉励说:“你在学校好好读书,努力往上考到更高的地方,未来成为一名有名望的学者,这样一来老爸也就能了无遗憾,将一切托付给你了!”。

       所以从这三个私生子的视角来看,他们认为他们未来都能继承父亲的10亿家产,于是更加努力的为父亲手下的公司卖力,为公司赚更多的钱。 

     

        解析上面的结构图:大富翁的10亿财产就是操作系统,三个儿子就好比三个进程,这3个儿子问父亲要钱,就是进程占用内存的各种资源。    当大儿子问富翁要钱时,肯定不可能一下子问他爹要10亿,这是不可能给的并且也不现实,但问老爸要个10万美金还是可以的,老爸给了;同理二三儿子也是一样。某个进程申请要资源,操作系统也只是一点一点的给,因为还要满足其它进程的需求。

如何画大饼?

       画大饼,就是给你描绘一个美好的未来,给你描绘一幅蓝图,比如上面的故事中,富豪在画的大饼里应该包含着:饼是给谁的? 什么时候给?在什么条件下能给? 打算给多少钱?”所以把这些属性汇总起来就像是给每个私生子描绘的一幅蓝图,而这副蓝图这块大饼对应到计算机数据结构的对象,就形成了一个完整的结构体。


        并且他在画饼的同时也需要管理,富豪给3个私生子画饼,同时富豪也得对他自己画的饼进行管理吧:比如要记住哪个大饼对应的是哪个私生子,画的大饼是否需要随着私生子的成长而进行相对应的改变? 相对应的就是操作系统给每个进程提供的地址空间,每个进程地址空间里面的具体属性不相同,并且地址空间的属性能够动态改变。而操作系统对这些地址空间(大饼)也需要进行管理,那么就需要用到我之前讲到的操作系统的管理理念:先描述,再组织。


        对管理对象先进行描述,所以在Linux中地址空间的本质是内核中的一个结构体,名叫:          struct mm_struct{ }


3.详谈进程地址空间: 

 

经过上面的讲解,我们已经明白了在上面这个地址空间中共有4GB大小(和内存大小一样),是2的32次方个字节大小,而每个字节都表示一个地址,也就是说共有2的32次方个地址。

这2的32次方个地址都是虚拟地址,且每个地址是由32位bit位组成,从0x0000....0000到0xFFFF....FFFF由低到高。

案例验证:

 运行结果:

地址空间的组成涉及到区域的划分:

        举个例子,小学某个班中一个男生和一个女生做同桌,两人共用一张100厘米长的桌子,两人为了公平起见划定了三八线,各占桌子的一半长度。但是这个男生有些胖,导致他总是超出划定的范围,女生很苦恼,总是强调该男生,但他总是超了范围。于是她又规定两人双方各占45厘米,中间有10厘米的缓冲地带,但是该男生还是占到女生的课桌,女生彻底生气了,规定男生到最后只有30厘米的位置可用。

        从这个例子可知:桌子好比虚拟地址空间,男女生划的三八线就是在进行区域的划分

        基于此,进程地址空间中那些堆区、栈区、数据区、代码区也都有各自的区域划分: 

 进程地址空间的结构体源码:

未完待续......,接下来请看我写的下一篇博客! 

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

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

相关文章

手机图片怎么提取文字?高效渠道一览

随着智能手机的普及&#xff0c;我们现在可以随时随地使用手机拍照记录生活中的点滴。然而&#xff0c;有时候我们拍照之后可能需要提取图片中的文字&#xff0c;比如拍下的菜谱、公告、名片等等。这时&#xff0c;我们就需要使用手机图片提取文字的功能。 - 采用OCR技术拍照识…

SpringBoot+Vue 实现网页版人脸登录、人脸识别!【全部开源】

介绍 FACE-UI 基于前后端分离Web端项目&#xff0c;主要实现了网页版的人脸登录&#xff0c;通过调取前端摄像头拍照&#xff0c;传入后台进行跟数据库人脸库的相似度比对。 技术点&#xff1a;Springboot&#xff0c;Mysql&#xff0c;JWT&#xff0c;VUE 2.X 等等技术实现&…

【Netty】使用 SSL/TLS 加密 Netty 程序(二十)

文章目录 前言一、SSL/TLS概述二、Sslhandler类 前言 回顾Netty系列文章&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构设计&#xff08;二&#xff09;Netty Channel 概述&#xff08;三&#xff09;Netty ChannelHandler&#xff08;四&#xff09;ChannelP…

EnjoyVIID部署

1、下载 git clone https://gitee.com/tsingeye/EnjoyVIID.git 2、导入数据库 创建表enjoyviid 导入数据库(修改数据库文件里的编码) EnjoyVIID/sql/tsingeye-viid.sql 3、修改配置 vim EnjoyVIID/tsingeye-admin/src/main/resources/application-dev.yml 修改数据库连接、re…

clickhouse的BACKUP/RESTORE命令介绍

clickhouse的数据备份和恢复功能在大数据运维中是非常常用的功能&#xff0c;目前也有很多比较优秀的开源方案可供选择&#xff0c;比如clickhouse-backup&#xff0c; 以及clickhouse自带的clickhouse-copier。 本文介绍使用clickhouse自带的BACKUP和RESTORE命令进行备份和恢复…

vue实现验证码登陆

我们在使用 vue进行前端开发时&#xff0c;都需要登录验证&#xff0c;而在登录的过程中&#xff0c;用户需要输入自己的用户名和密码&#xff0c;如果是输错的话还需要进行再次输入。这样不仅容易造成用户密码泄露&#xff0c;还会影响用户体验。因此在我们的系统中都会存在验…

【深入浅出Spring Security(二)】Spring Security的实现原理

Spring Security的实现原理 一、实现原理二、内置Filter以及默认加载的Filter三、自动配置分析&#xff08;SpringBootWebSecurityConfiguration&#xff09;ConditionalOnMissingBean 四、自己配置SecurityFilterChain 一、实现原理 在 Spring Security 中&#xff0c;认证、…

交直流混合配电网潮流计算(统一求解法)

目录 1 主要内容 算例模型 统一求解法迭代方程 算法流程图 2 部分代码 3 程序结果 4 程序链接 1 主要内容 该程序为matlab代码&#xff0c;采用统一求解法对交直流混合配电网进行潮流计算&#xff0c;统一迭代法又称统一求解法&#xff0c;其思路是将混联系统中的交流网…

FPGA串口发送数据

module Uart(input clk, //H3input rst, //F10output reg TX //串口发送脚M12 );reg[9:0] buffer 10b1_1100_1010_0; //接收方&#xff1a;0XCA parameter SND_T 5208; //9600bps reg [15:0] cnt 0; //数据宽度计数 always (posedge clk or negedge rst) beginif(!rs…

Unity游戏优化指南大全(持续更新中!)

Unity游戏优化指南大全 三个官方优化提示&#xff1a; 性能和优化 (Performance and Optimization) - 关于性能分析器以及性能和优化技巧的 Unity 学习教程。Best practices for performance optimization in Unity - 优化应用程序的最佳实践指南。Ultimate guide to profili…

【gstreamer】入门介绍

概述 GStreamer是一个基于流媒体的框架&#xff0c;是一个开放源代码的多媒体框架&#xff0c;用于创建音频和视频处理应用程序。它是一个运行在多个操作系统上的跨平台框架&#xff0c;支持多种不同的多媒体格式。 GStreamer框架的核心是基于插件的体系结构&#xff0c;插件…

GEE:绘制一个点的时间序列折线图,并且显示所有可用影像(逐日合成影像集合)

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine (GEE)平台上,对“COPERNICUS/S5P/NRTI/L3_CO”数据集逐日合成,并可视化所有影像,根据逐日合成数据集绘制指定点的时间序列折线图。 图1 每天合成图像可视化 图2 一个点的每天合成时间序列折线图 文章目录 一、代…

VWS型振弦式应变计安装埋设时要注意什么

VWS型振弦式应变计是一种常见的应变测量设备&#xff0c;它是通过将振弦安装在被测结构上来实现应变测量。南京峟思专业的应变计生产厂家提醒大家&#xff0c;在安装和埋设VWS型振弦式应变计时&#xff0c;需要注意以下事项&#xff1a; 南京峟思工程仪器振弦式应变计 ​​​​…

84.Rem和max-width如何工作

max-width 首先我们先看普通的width是什么样的效果&#xff01; 首先给个测试的div <div class"test">TEST</div>● 然后CSS给定一个宽度 .test {width: 1000px;background-color: red;padding: 100px; }如上图&#xff0c;不管你的浏览器窗口如何改变…

记一次处理Spring-boot使用dubbo类型转换失败的问题

第一步、使用父类接收子类&#xff0c;类型转换失败&#xff0c;猜测是不是父子类不能接收&#xff0c;&#xff08;应该不可能&#xff0c;但还是试下&#xff09;&#xff1b; 第二步、使用同一个类接收&#xff0c;还是类型转换失败&#xff1b; com.book.common.result.Res…

将 Rust 程序编译为 WebAssembly

Rust 笔记、WebAssembly 将 Rust 程序编译为 WebAssembly 的知识与实践 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blo…

浅谈安科瑞霍尔传感器在转速测量中的选型与应用

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘 要&#xff1a;在现代工业生产中存在许多需要转速测量的方面&#xff0c;针对转速测量方法落后、只能进行接触式测量等问题&#xff0c;提出把霍尔传感器应用于工业生产中 , 利用霍尔效应测量转速&#xff0c;具有动…

【linux解压和打包文件】

TOC 打包成zip文件 指令 zip zip -r -q -o html.zip html/ -r 参数表示递归打包包含子目录的全部内容&#xff0c;-q 参数表示为安静模式&#xff0c;即不向屏幕输出信息&#xff0c;-o 表示输出文件&#xff0c;需在其后紧跟打包输出文件名。解压zip文件 1.unzip -q …

数字化时代,企业面临哪些共同的挑战?

在这种全新的社会、商业环境下&#xff0c;各行各业的企业都开始寻求探索新的商业模式&#xff0c;通过转型适应当前时代的转变&#xff0c;促进业务健康持续的发展。所以数字化成为了企业进行转型的工具&#xff0c;也成为了众多领域内企业对未来的共识。 一、管理挑战 ●经…

C++服务器框架开发3——协程与线程的简单理解/并发与并行

该专栏记录了在学习一个开发项目的过程中遇到的疑惑和问题。 其教学视频见&#xff1a;[C高级教程]从零开始开发服务器框架(sylar) 上一篇&#xff1a;C服务器框架开发2——头文件memory/typedef C服务器框架开发3——协程与线程的简单理解/并发与并行 目前进度协程与线程的简…