当前位置: 首页 > news >正文

Linux程序的地址空间

Linux程序的地址空间

📟作者主页:慢热的陕西人

🌴专栏链接:Linux

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

本博客主要内容深刻理解了什么程序或者进程的地址空间,以及它存在的意义,和操作系统内部是如何实现进程地址空间的

文章目录

  • Linux程序的地址空间
    • 1.一个测试代码
      • 运行的结果:
      • 1.1可以得到的结论
    • 2.引入地址空间
      • 2.1小故事
      • 2.2 代码区,数据区,堆区,等等这些区域该如何理解
    • 3. 地址空间是什么?为什么?怎么办?
      • 3.1为什么要有地址空间
      • 3.2 malloc的本质
      • 3.3 重新理解地址空间

1.一个测试代码

我们先运行一个测试代码:

#include<stdio.h>
#include<unistd.h>
#include<assert.h>int g_val = 100; //全局变量int main()
{pid_t id = fork();assert(id >= 0);if(id == 0)
{//childwhile(1){//此处反斜杠是为了让代码可以换行printf("我是子进程,我的PID是:%d,我的PPID是:%d,g_val:%d, &g_val:%p\n",\getpid(), getppid(), g_val, &g_val);                                                                      sleep(1);g_val++;}
}
else
{while(1){//父进程printf("我是父进程,我的PID是:%d,我的PPID是:%d,g_val:%d, &g_val:%p\n",\getpid(), getppid(), g_val, &g_val);sleep(1);}
}
return 0;
}

运行的结果:

image-20231106170746600

1.1可以得到的结论

我们发现竟然指向相同地址的变量,却出现了不同值的情况,这其实是因为发生了写时拷贝,并且我们佐证了,子进程可以对全局变量进行修改并且不影响父进程全局变量的值,从而证明了进程具有独立性。

同时我们也可以看出这里的地址不是物理地址,因为假设是物理地址,我们不可能在同一块物理地址上,取到不同的值,所以我们认为这是一个虚拟地址or线性地址

2.引入地址空间

2.1小故事

我们用一个大富翁和私生子的故事来引入地址空间的概念:

大富翁有十亿美金,但是他有四个私生子(A , B, C , D);

image-20231106223351434

A:做生意的 | B:卖化妆品 | C:哈弗读书 | D:高中辍学的混混

并且ABCD并不知道彼此的存在,并且他们都坚信自己最终能够继承大富翁的遗产;

某一天大富翁对着A说:你好好做你的生意,将来等我去世的时候我的十亿家产全都是你的。

对B说:你的化妆品卖的挺好,你听老爹的话,等老爹到时候西去的时候,我的家产都是你的。

同样对C和D都是一样的画饼。

所以现在ABCD每个人脑子里都有一张饼,就是老爹的十亿。😆

有一天A来找到大富翁,告诉他说自己需要五万美金,做生意需要买一块手表,会见自己和合作伙伴,但是自己的生意目前周转不开,大富翁一想,才五万美金,大手一挥直接给A了。

C联系大富翁,并给他说:自己在学校念书,没有生活费了,想问老爹要1000美金的生活费。老爹一听,小钱大手一挥又给了。(以上两个是进程向操作系统申请较小的内存空间,操作系统当然允许)

有一天D找到大富翁说:我在社会上遇到一点事,需要一些钱摆平一下,你给我5000万美金吧。老爹一听,说:一边去,我这么多钱也不能这么花。D骂骂咧咧的走了。(进程向操作系统申请很大的内存空间,操作系统拒绝了)

…这是ABCD也都会认为自己最终如果想要那十亿美金**(饼)**,他们都还是会获得的。

但其实如果ABCD每个人向大富翁索要几千几万,大富翁都会给予。但是如果向大富翁索要很多,几千万几亿的情况下,大富翁是完全可以直接拒绝的。

这里我们引入第一个概念:

进程的地址空间:就是大富翁给每个私生子画的饼。

那么最后揭晓:十亿美金相当于内存,大富翁相当于操作系统


那么我们想想大富翁有没有必要将自己的“饼”管理起来呢?

答案是有必要的先描述在组织,因为如果大富翁的儿子多了,并且他画的饼多了之后,他也会忘记的。

2.2 代码区,数据区,堆区,等等这些区域该如何理解

我们用一个小故事引入:

时间来到小学时代,有一对同桌,小花和小胖,两个人**共用一张大桌子。(内存空间)**然而小胖,不爱干净,男孩子很爱运动,所以身上老有一股汗味。小花就不满意了,二话不说先把小胖揍了一顿,告诉他:回家之后好好洗一洗,回去告诉你爸爸妈妈,我们上幼儿园要讲卫生。第二点,你从今天开始不能再欺负我了,要不然我再揍你一顿。

小花告诉小胖:我们以中间这根线为界谁都不许越界,不能把你的东西放到我这边来,也不能把你的胳膊放到我这边来。

小花画这条线的本质:叫做区域划分!如下这样:

struct area
{int start;int end;
}
struct area xiaohua_area = {1, 50};
struct area xiaopang_area = {50, 100};

地址空间本质就是线性结构的

image-20231107145145203

不管是32位还是64位机器,我们并不需要记录地址空间是多少GB的,原因是:不管是多少位的机器,在操作系统刚刚开始加载的时候就确定好了。

那么有了之前的铺垫,我们就可以地址空间是怎么在mm_struct中划分的;

struct mm_struct ---- 4GB
{long code_start; //代码区的起始long code_end; //代码区的结束long init_start;long init_end;....long brk_start; //堆区的起始long brk_end; //堆区的结束long stack_start; //栈区的起始long stack_end; //栈区的结束
}

那么如果限定了区域,那么区域之间的数据是什么?

例如[1000,2000],1000和2000被称作我们的地址,那么他们之间的区域就被称作虚拟地址or线性地址

那么我们故事在继续…

小花和小胖画好了三八线之后,一段时间,两个人都很受规矩,但是小胖却很调皮,小胖总是将自己的胳膊放到三八线左侧,或者将自己的书包和都扔到小花的桌子上,这强烈的引起了小花的不满,小花就将小胖揍了一顿,然后更改了三八线的位置…

那么对于小花来说,叫做区域扩大。对于小胖来说叫做区域缩小;

体现在mm_struct中呢就是:

xiaohua_area.end = 75;
xiaopang_area.start = 75;

那么对应到我们的地址空间上,对于我们的栈区,堆区等的区域扩大和缩小也是一样的,都是更改我们的startend.

3. 地址空间是什么?为什么?怎么办?

数据和代码真正是存储在内存中。

是什么?

虚拟地址空间是一种在操作系统内部为进程创建出来的具体的数据结构对象,让进程以同意的视角来查看内存。

image-20231107153416685

虚拟地址会经过也变转化为物理地址,我们平时使用的地址都是虚拟地址,当我们有了虚拟地址,我们就可以通过页表找到物理地址中对应的位置,从而将物理地址中存储的内容放到我们的CPU中。

接下来我们用一幅图来解释最开始的父进程和子进程,查看相同地址的内存,却看到不同值的问题。

首先操作系统为每一个进程维护一张页表,用来存储虚拟地址和物理地址的映射关系。

image-20231107155544493

最开始的时候父子进程的虚拟地址都是指向最开始的g_val的位置,但是当子进程尝试修改g_val的时候,这时候操作系统会在物理地址的另一个位置拷贝一份g_val的值,然后修改,并且将这个物理地址存储到子进程页表刚刚指向原物理地址的位置。

并且这里也是体现了进程的独立性。

同时我们这里也可以解释最开始的之前的代码fork()函数貌似有两个返回值的问题:

首先fork在返回的时候,父子进程都有了,return两次,id是不是也是pid_t类型定义的变量呢?那么返回的本质就是写入,父子进程谁先写入,就发生了写时拷贝。造成了一个变量,有两个值的情况。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{     pid_t ret = fork();if(ret == 0){ //子进程printf("我是子进程,我的pid是:%d,我的父进程是:%d",getpid(),getppid()); sleep(1);        }else if(ret > 0){    //父进程while(1){ printf("我是父进程,我的pid是:%d,我的父进程是:%d"getpid(),getppid());sleep(2);   }                          }                                                                                            return 0;                                                                                  
} 

3.1为什么要有地址空间

如果没有地址空间,我们的进程的pcb只能直接指向物理内存中的该进程相关的数据和代码。

这样就会产生很多不安全的问题,以及效率问题。

①防止地址随意访问,保护物理内存和其他进程

②将进程管理和内存管理解耦合

③可以让进程以统一的视角,看待自己的代码和数据

3.2 malloc的本质

当我们向操作系统申请内存,操作系统立马给你,还是需要的时候再给你呢?

那么毫无疑问肯定是我们需要的时候才会给我们。

①操作一同不会允许任何的浪费和不高效

②申请内存 != 立马使用

③在你申请成功之后,和你使用之前,有很小一段的时间窗口,----这个空间没有被正常使用,但是别人也用不了,—闲置状态。

那么malloc的时候申请空间,我们操作系统只会再地址空间上对应的堆区进行申请空间,那么这里就是我们之前提到的,操作系统会为我们的堆区进行区域扩大,也就是去操作我们的mm_struct中的brk_endbrk_start,然后去页表中存储,但是不会再物理地址上去帮我们申请。相当于做了一半的映射,这时候直到当我们的进程需要用到这片地址的时候,操作系统才会帮我们去完成页表和物理地址的映射。

当操作系统检测到我们需要内存的时候才给我们申请,或者检测到我们的代码和数据不在内存,当我们需要的时候给我们换入,这样的操作叫做缺页中断

总结一句就是malloc在申请空间的时候,我们的操作系统不会立马分配空间,而是在我们需要使用的时候才给我们分配,这就是malloc的本质。

并且正是因为有了地址空间的存在,我们的进程也不关心,它的数据和代码存储在物理地址的任意位置。

**进程管理:**操作系统管理进程和地址空间的过程,叫做进程管理。

内存管理: 操作系统管理页表和物理内存之间的映射的过程,叫做内存管理。

并且操作系统将进程和物理内存之间分成进程管理内存管理的过程,叫做解耦合。

3.3 重新理解地址空间

首先我们想一想我们的程序在被编译的时候,没有被加载到内存,请问,我们的程序内部有没有地址呢?

答案肯定是有的,源代码被编译的时候,就是按照虚拟地址空间的方式进行对代码和数据早就已经编好了对应的编址。

我们不能认为虚拟地址这样的策略只会影响操作系统,还要让我们的编译器也要遵守这样的规则。(Linux系统中的可执行文件的格式是ELF格式)

进程的代码和数据需要一直在内存中吗?

答案是不一定的,就算是我们要运行一个进程,我们操作系统也不会一次将这个进程所对应的代码和数据加载到内存中。

操作系统一般是边加载边执行,这也是地址空间的意义。

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述

相关文章:

Linux程序的地址空间

Linux程序的地址空间 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容深刻理解了什么程序或者进程的地址…...

Docker安装Minio(稳定版)

1、安装 docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z docker run -p 9000:9000 minio/minio:RELEASE.2021-06-17T00-10-46Z server /data 2、访问测试 3、MinIO自定义Access和Secret密钥 要覆盖MinIO的自动生成的密钥&#xff0c;您可以将Access和Secret密钥设为…...

大数据毕业设计选题推荐-超级英雄运营数据监控平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

视频转码教程:轻松制作GIF动态图,一键高效剪辑操作

随着社交媒体的兴起&#xff0c;GIF动态图已经成为了人们表达情感、分享精彩瞬间的重要方式。而将视频转化为GIF动态图&#xff0c;不仅可以方便地在社交媒体上分享&#xff0c;还可以延长视频的播放时长&#xff0c;吸引更多的观众。本篇文章将为大家介绍如何将视频轻松转化为…...

Seata分布式事务实现原理

Seata可以解决分布式事务问题&#xff0c;利用GlobalTransacational(name "fsp-create-order",rollbackFor Exception.class)注解就可以实现全局的事务管理&#xff0c;但是我们需要明白原理的实现。 我们举例创建订单——>调减库存——>调扣余额——>改订…...

Rasa NLU中的组件

Rasa NLU部分主要是解决NER&#xff08;序列建模&#xff09;和意图识别&#xff08;分类建模&#xff09;这2个任务。Rasa NLP是一个基于DAG的通用框架&#xff0c;图中的顶点即组件。组件特征包括有顺序关系、可相互替换、可互斥和可同时使用。有向无环图&#xff08;DAG&…...

redis笔记 三 redis持久化

文章目录 Redis持久化RDB持久化执行时机RDB原理小结 AOF持久化AOF原理AOF配置AOF文件重写 RDB与AOF对比 Redis持久化 redis持久化是为了解决redis宕机时丢失数据的问题&#xff0c;Redis有两种持久化方案&#xff1a; RDB持久化AOF持久化 RDB持久化 RDB全称Redis Database …...

k8s-----数据存储

目录 一、数据存储的概念 二、基本存储 1、EmptyDir存储卷 2、hostPath存储卷 3、nfs共享存储卷 三、高级存储 1、PV&#xff08;持久化卷&#xff09; 2、PVC&#xff08;持久化卷声明&#xff09; 3、静态PV实验 4、动态PV实验 4.1 在stor01节点上安装nfs&#xf…...

macOS电池续航工具:Endurance中文

Endurance for Mac是一款强大而实用的电池管理和优化软件&#xff0c;专为MacBook设计。通过智能调整系统设置和管理后台应用&#xff0c;它能有效延长电池续航时间&#xff0c;提升工作和娱乐效率&#xff0c;成为你在各种场合下的得力助手。 Endurance for Mac软件的功能特色…...

栈(定义,基本操作,顺序存储,链式存储)

目录 1.栈的定义1.重要术语2.特点 2.栈的基本操作3.栈的顺序存储1.顺序栈的定义2.基本操作1.初始化2.进栈3.出栈4.读栈顶 3.共享栈 4.栈的链式存储 1.栈的定义 栈( Stack&#xff09;是只允许在一端进行插入或删除操作的线性表。 一种受限的线性表&#xff0c;只能在栈顶进行插…...

在HTML单页面中,使用Bootstrap框架的多选框如何提交数据

1.引入Bootstrap CSS和JavaScript文件&#xff1a;确保在HTML页面的标签内引入Bootstrap的CSS和JavaScript文件。可以使用CDN链接或者下载本地文件。 <link rel"stylesheet" href"https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css&q…...

当爱好变成职业,会不会就失去了兴趣?

当爱好变成职业&#xff0c;会不会就失去了兴趣&#xff1f; 当兴趣变成职业 1、学习能力变强了&#xff0c;积极主动性增加了。 2、学习努力变现了&#xff0c;赚到的更钱多了。 3、赚钱能力变强了&#xff0c;反过来再次促使兴趣发展&#xff08;兴趣更大了....干劲更足了&…...

3-知识补充-MVC框架

3-知识补充-MVC框架 文章目录 3-知识补充-MVC框架MVC概述M、V、C各自负责功能及常用包MVC框架图非前后端分离框架图前后端分离框架图 MVC概述 MVC&#xff08;Model、View、Controller&#xff09;是软件工程中的一种**软件架构模式&#xff0c;它把软件系统分为模型、视图和控…...

leetcode:141. 环形链表

一、题目 函数原型&#xff1a; bool hasCycle(struct ListNode *head) 二、算法 判断不是环形链表&#xff0c;只需遍历链表找到空结点即可。 判断是环形链表&#xff0c;由于链表是环形的&#xff0c;遍历不会永远不会结束。所以要设置快慢指针&#xff0c;慢指针一次走一步&…...

了解企业邮箱的外观和功能特点

企业邮箱是什么样子的&#xff1f;企业邮箱不是单一产品&#xff0c;而是由一系列电子邮件服务组成的生态系统。这些服务包括但不限于邮件服务器、客户端、安全解决方案等。这些服务共同构成了企业邮箱的基础设施。 在外观上&#xff0c;企业邮箱和个人邮箱没有太大区别。用户通…...

配置阿里云镜像加速器 -docker

1.百度aliyun 2.找到镜像服务ACR 3.搞一个个人版&#xff0c;身份验证一下就行了很简单 4.找到镜像加速器Centos 5.执行下面4条命令&#xff1a;4条命令直接从上面操作文档中粘贴&#xff0c;不容易出错 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<…...

11 抽象向量空间

抽象向量空间 向量是什么函数什么是线性推论向量空间 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 向量是什么 可以是一个箭头&#xff0c;可以是一组实数&#xff0c;即一个坐标对。 箭头在高维&#xff08;4维&#xff0c;甚至更高&#xff09;空间&…...

干洗店洗鞋店管理系统app小程序;

干洗店洗鞋店管理系统是一款专业的洗衣店管理软件&#xff0c;集成了前台收费收银系统、会员卡管理系统和财务报表系统等强大功能。界面简洁优美&#xff0c;操作直观简单。这款系统为干洗店和洗衣店提供了成本分析、利润分析、洗衣流程管理等诸多实用功能&#xff0c;用全新的…...

NOIP2023模拟13联测34 总结

NOIP2023模拟13联测34 总结 文章目录 NOIP2023模拟13联测34 总结比赛过程题目A. origen题目大意思路 B.competition题目大意思路 C. tour题目大意 D.abstract题目大意 比赛过程 看了一下题&#xff0c;感觉就 T 2 T2 T2 有一点思路。 T 1 T1 T1 先打一个 30 30 30 分暴力&am…...

Python武器库开发-常用模块之subprocess模块(十九)

常用模块之subprocess模块(十九) subprocess模块介绍 subprocess 模块允许我们启动一个新进程&#xff0c;并连接到它们的输入/输出/错误管道&#xff0c;从而获取返回值。subprocess 它可以用来调用第三方工具&#xff08;例如&#xff1a;exe、另一个python文件、命令行工具…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...