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进程概念到这里也结束了,后面我将带大家走进进程控制。
谢谢大家支持本篇到这里就结束了

相关文章:
Linux进程——进程地址空间
前言:在讲完环境变量后,相信大家对Linux有更进一步的认识,而Linux进程概念到这也快接近尾声了,现在我们了解Linux进程中的地址空间! 本篇主要内容: 了解程序地址空间 理解进程地址空间 探究页表和虚拟地址空…...
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三)
基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 大家继续看 https://lilianweng.github.io/posts/2023-06-23-agent/的文档内容 第二部分:内存 记忆的类型 记忆可以定义为用于获取、存储、保留以及随后检索信息的过程。人脑中有多…...
python3如何安装bs4
在python官网找到beautifulsoup模块的下载页面,点击"downloap"将该模块的安装包下载到本地。 将该安装包解压,然后在打开cmd,并通过cmd进入到该安装包解压后的文件夹目录下。 在该文件目录下输入"python install setup.py&quo…...
docker容器技术篇:rancher管理平台部署kubernetes集群
rancher管理平台部署kubernetes集群 Rancher 是一个 Kubernetes 管理工具,让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托管服务提供商的集群,创建节点并安装 Kubernetes,或者导入在任何地方运行的现…...
【计算机网络原理】初识网络原理和一些名词解释
˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…...
车载电子电器架构 —— 关于bus off汇总
车载电子电器架构 —— 关于bus off汇总 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…...
Linux函数
目录 一、脚本函数 1.1 创建函数 1.2 使用函数 二、函数返回值 2.1 默认的退出状态码 2.2 使用return命令 2.3 使用函数输出 三、在函数中使用变量 3.1 向函数传达参数 3.2 在函数中处理变量 四、数组变量和函数 4.1 向函数中传递数组 4.2 从函数中返回数组 五、函数…...
如何查看centos7中Java在哪些路径下
在 CentOS 7 上,你可以通过几种方式查找安装的 Java 版本及其路径。以下是一些常用的方法: 1. 使用 alternatives 命令 CentOS 使用 alternatives 系统来管理同一命令的多个版本。你可以使用以下命令来查看系统上所有 Java 安装的配置: su…...
信息安全-古典密码学简介
目录 C. D. Shannon: 一、置换密码 二、单表代替密码 ① 加法密码 ② 乘法密码 ③密钥词组代替密码 三、多表代替密码 代数密码 四、古典密码的穷举分析 1、单表代替密码分析 五、古典密码的统计分析 1、密钥词组单表代替密码的统计分析 2、英语的统计规…...
面试题 01.05. 一次编辑
字符串有三种编辑操作:插入一个英文字符、删除一个英文字符或者替换一个英文字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。 示例 1: 输入: first "pale" second "ple" 输出: True示例 2: 输入: first &qu…...
针对头疼的UDP攻击如何定制有效的防护措施
分布式拒绝服务攻击(Distributed Denial of Service)简称DDoS,亦称为阻断攻击或洪水攻击,是目前互联网最常见的一种攻击形式。DDoS攻击通常通过来自大量受感染的计算机(即僵尸网络)的流量,对目标…...
怎么制作流程图?介绍制作方法
怎么制作流程图?在日常生活和工作中,流程图已经成为我们不可或缺的工具。无论是项目规划、流程优化,还是学习理解复杂系统,流程图都能帮助我们更直观地理解和表达信息。然而,很多人可能并不清楚,其实制作流…...
棱镜七彩参编《网络安全技术 软件供应链安全要求》国家标准发布
据全国标准信息公共服务平台消息显示,《网络安全技术 软件供应链安全要求》(GB/T 43698-2024)国家标准已于2024年4月25日正式发布,并将于2024年11月1日正式实施。棱镜七彩作为主要编制单位之一参与该国家标准的编制,为…...
Keepalived实现LVS高可用
6.1 KeepalivedLVS集群介绍 Keepalived和LVS共同构建了一个高效的负载均衡和高可用性解决方案:LVS作为负载均衡器,负责在集群中的多个服务器间分配流量,以其高性能和可扩展性确保应用程序能够处理大量的并发请求;而Keepalived则作…...
【力扣】1089.复写零
原题链接:. - 力扣(LeetCode) 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不…...
Golang实践录:gin框架使用自定义日志模块
本文介绍在 Golang 的 gin 框架中使用自定义日志模块的一些方法。 背景 很早之前就实现并使用了自己封装的日志模块,但一直没有将gin框架内部的日志和日志模块结合。gin的日志都是在终端上打印的,排查问题不方便。趁五一假期,集中研究把此事…...
Django之配置数据库
一,创建项目 二,将项目的setting.py中的 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }替换成如下(以mysql为例) DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: …...
Ajax 笔记02
01 jq中的ajax方法中的dataType属性 dataType属性的属性值有以下几种: xml 返回数据按照xml解析 json 返回的数据按照json代码解析 script 返回的数据按照js代码解析 text 把返回的数据按照普通文本解析 jsonp 跨域 json: javascript object notation(js对象简谱) json整体…...
【隧道篇 / WAN优化】(7.4) ❀ 03. WAN优化的原理 ❀ FortiGate 防火墙
【简介】相信对WAN优化感兴趣的人都会有疑问,WAN优化真的有作用吗?如果真的有作用,那是根据什么原理呢?让我们来更深入的了解一下。 客户端和服务器端 其实很多人在一开始看到WAN优化这个词,就自然的以为上网速度太慢&…...
网络爬虫概述与原理
网络爬虫概述与原理 网络爬虫简介狭义上理解功能上理解常见用途总结 网络爬虫分类通用网络爬虫聚焦网络爬虫增量网络爬虫深度网络爬虫 网络爬虫流程网络爬虫采集策略深度有限搜索策略广度优先搜索策略 网络爬虫简介 通过有效地获取网络资源的方式,便是网络爬虫。网…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
