Linux进程学习【进程地址】
✨个人主页: Yohifo
🎉所属专栏: Linux学习之旅
🎊每篇一句: 图片来源
🎃操作环境: CentOS 7.6 阿里云远程服务器
Perseverance is not a long race; it is many short races one after another.
- 毅力不是一场漫长的比赛;是许多短跑一个接一个。
文章目录
- 📘前言
- 📘正文
- 📖问题引入
- 📖虚拟空间划分
- 📖真实空间分布
- 🖋️代码实现
- 🖋️问题反思
- 📖进程地址空间
- 🖋️虚拟地址
- 🖋️页表+MMU
- 🖋️写时拷贝
- 🖋️内存申请
- 📖虚拟地址空间存在的意义
- 📘总结
📘前言
对于 C/C++
来说,程序中的内存包括这几部分:栈区
、堆区
、静态区
等,其中各个部分功能都不相同,比如函数的栈帧位于 栈区
,动态申请的空间位于 堆区
,全局变量和常量位于 静态区
,区域划分的意义是为了更好的使用和管理空间,那么 真实物理空间
也是如此划分吗?多进程运行
时,又是如何区分空间的呢?写时拷贝
机制原理是什么?本文将对这些问题进行解答
内存条:真实的物理空间,用来存储各种数据
📘正文
📖问题引入
地址是唯一的,对地址进程编号的目的是为了不冲突
这是个耳熟能详的概念,在 C语言
学习阶段,我们可以通过对变量 &
取地址的方式,查看当前变量存储空间的首地址信息
#include <stdio.h>int main()
{const char* ps = "这是一个常量字符串";printf("字符串地址:%p\n", ps); //%p 专门用来打印地址信息return 0;
}
利用前面学习的 fork
函数创建子进程,使得子进程和父进程共同使用一个变量
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main()
{int val = 10;pid_t id = fork();if(id == 0){val *= 2; //刻意改变共享值printf("我是子进程,pid:%d ppid:%d 共享值:%d 共享值地址:%p\n", getpid(), getppid(), val, &val);exit(0);}waitpid(id, 0, 0);printf("我是父进程,pid:%d ppid:%d 共享值:%d 共享值地址:%p\n", getpid(), getppid(), val, &val);return 0;
}
对于同一块空间,读取到了不同的值,是不可能出现这种情况的
因为真实地址都是 唯一
的,分析:
- 不同的空间出现同名的情况
- 父子进程使用的真实物理空间并非同一块空间!
原因:
- 当子进程尝试修改共享值时,发生
写时拷贝
机制 - 语言层面的程序空间地址不是真实物理地址
- 一般将此地址称为
虚拟地址
或线性地址
结论: 语言层面的地址都是虚拟地址,用户无法看到真实的物理地址,由 OS 统一管理
📖虚拟空间划分
一般用户的认知中,C/C++
程序内存分布如下图所示,直接表示内存中的各个部分
📖真实空间分布
但实际上的空间分布是这样的:
如果有多个进程(真实地址空间只有一份),此时情况是这样的:
🖋️代码实现
在实现虚拟地址空间时,是用结构体 mm_struct
实现的
同 task_struct
一样,mm_struct
中也包含了很多成员,比如不同区域的边界值
//简单展示其中的成员信息
mm_struct
{//代码区域划分unsigned long code_start;unsigned long code_end;//堆区域划分unsigned long heap_start;unsigned long heap_end;//栈区域划分unsigned long stack_start;unsigned long stack_end;//还有很多其他信息……
}
每个进程都会有这样一个 mm_struct
,其中的区域划分就是虚拟地址空间
通过对边界值的调整,可以做到不同区域的增长,如堆区、栈区扩大
mm_struct
中的信息配合 页表
+MMU
在对应的真实空间中使内存(程序寻址)
🖋️问题反思
此时可以理解为什么会发生同一块空间能读取到不同值的现象了
- 父子进程有着各自的
mm_struct
,其成员起始值一致 - 对于同一个变量,如果未改写,则两者的虚拟地址通过
页表
+MMU
转换后指向同一块空间 - 发生改写行为,此时会在真实空间中再开辟一块空间,拷贝变量值,让其中一个进程的虚拟地址空间映射改变,这种行为称为
写时拷贝
刚开始,父子进程共同使用同一块空间
当子进程修改共享值后
📖进程地址空间
下面来好好谈谈 进程地址空间
(虚拟地址)
🖋️虚拟地址
在早期程序中,是没有虚拟地址空间的,对于数据的写入和读取,是直接在物理地址上进行的,程序与物理空间直接打交道,存在以下问题:
- 假设存在野指针问题,此时可能直接对物理内存造成越界读写
- 程序运行时,每次都需要大小为
4GB
的内存使用,当进程过多时,资源分配就会很紧张,引起进程阻塞,导致执行效率下降 - 动态申请内存后,需要依次释放,影响整体效率
为了解决各种问题,大佬们提出了 虚拟地址空间
这个概念,有了 虚拟空间
后,当进程创建时,系统会为其分配属于自己的 虚拟空间
,需要使用内存时,通过 寻址
的方式,使用物理地址上的空间即可
- 多个进程互不影响,动态使用,做到
效率
、资源
双赢 - 发生越界行为时,
寻址
机制会检测出是否发生越界行为,如果发生了,能在其对物理地址造成影响前进行拦截 - 因为每个进程都有属于自己的空间,
OS
在管理进程时,能够以统一的视角进行管理,效率很高
光有 虚拟地址空间 是不够的,还需要一套完整的 ‘‘翻译’’ 机制进行程序寻址,如 Linux
中的 页表
+ MMU
🖋️页表+MMU
页表
本质上就是一张表,操作系统
会为每个进程
分配一个页表
,该页表
使用物理地址
存储。当进程
使用类似malloc
等需要映射代码或数据
的操作时,操作系统
会在随后马上修改页表
以加入新的物理内存
。当进程
完成退出时,内核会将相关的页表项删除掉,以便分配给新的进程
原话出处:ARM体系架构——MMU
系统底层机制的研究是非常生涩的,这里简言之就是 页表
记录信息,通过 MMU
机制进行寻址使用内存,假设目标空间为只读区域(比如数据段、代码段),在进行空间开辟时,会打上只读权限标签。后续对这块进行写入操作时,会直接拒绝
对于这种机制感兴趣的同学可以点击下面这几篇文章查看详细内容:
Linux的虚拟内存详解(MMU、页表结构)
ARM体系架构——MMU
逻辑地址、页表、MMU等
🖋️写时拷贝
Linux
中存在一个很有意思的机制:写时拷贝
这是一种 赌bo 行为,OS
此时就赌你不会对数据进行修改,这样就可以 使多个 进程
在访问同一个数据时,指向同一块空间,当发生改写行为时,再新开辟空间进行读写
这种行为对于内置类型来说感知还不是很强,但如果是自定义类型的话,写时拷贝
行为可以在某些场景下减少 拷贝构造
函数的调用次数(尤其是 深拷贝
),尽可能提高效率
可以通过一个简单的例子来证明此现象
//计算 string 类的大小
#include <iostream>
#include <string>
using namespace std;int main()
{string s;cout << sizeof(s) << endl;return 0;
}
原因:
g++
中的string
对象创建后,它就赌你不会直接改写,所以实际对象为一个指针类型(64位环境下为8字节),当发生改写行为时,触发写时拷贝
机制,再进行其他操作
🖋️内存申请
值得注意的是,在进行动态内存申请时,OS
也并非直接去申请好内存,而是先判断是否有足够的内存,如果有,就在 页表
中记录相应信息(这种行为叫做 缺页中断
),当程序实际使用到这块空间时,OS
才会去申请内存给程序使用
OS是一个讲究人,不允许任何空间浪费或低效率行为
假设没有 缺页中断
机制,给程序分配空间后,程序又不用,此时空间属于闲置状态,这是不被 OS
认可的低效浪费行为
图片来源:3.2.2 OS之请求分页管理方式(请求页表、缺页中断机构、地址变换机构)
📖虚拟地址空间存在的意义
总结一下,虚拟内存+页表+MMU
这种管理方式的好处:
- 防止地址随意访问,保护物理内存与其他进程(权限设置)
- 将
进程管理
和内存管理
进行解耦
,方便OS
进行更高效的管理 - 可以让进程以统一的视角看待自己的代码和数据
📘总结
以上就是本篇关于 Linux
进程学习【进程地址】的全部内容了,我们从一个有趣的小问题切入,见识到了 虚拟地址空间
与 物理地址空间
的奇妙关系,在种种机制的加持之下,OS
对进程的管理变得更加得心应手,系统也因此得以高效运行
如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!
如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正
相关文章推荐
Linux进程学习【环境变量】 Linux进程学习【进程状态】 Linux进程学习【基本认知】
===============
Linux工具学习之【gdb】 Linux工具学习之【git】 Linux工具学习之【gcc/g++】 Linux工具学习之【vim】
相关文章:

Linux进程学习【进程地址】
✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…...

系统调用——文件操作相关函数
1.open open, creat - open and possibly create a file or device 打开一个文件,也可能创建一个文件,返回文件描述符 //头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> //接口 int open(const char *pa…...

做互联网自媒体创业的月薪收入真的能过万吗?
搞自媒体创业有前途吗?收入月薪过万是真的吗? 自媒体创业是一种新兴的创业方法,它的远景十分广阔。自媒体创业能够让人们在自己的兴趣爱好和专业范畴上发挥自己的才能,一起也能够获得不错的收入。可是,月薪过万并不是…...
Kubernetes (k8s) 污点(Taint)、容忍介绍、示例
Kubernetes (k8s) 污点(Taint) 是一种机制,用于标记一个节点(Node)不可被调度的状态。它可以将一个污点标记添加到节点上,以防止 Pod 被调度到该节点上。污点可以用于实现各种策略,例如分离故障…...
多团队协作构建可观测性
实施 SRE 工程,守护系统的可靠性是一个⻓期的工作,需要开发、测试、运维以及 SRE 整个团队的努力。而可观测性平台天生就是为 SRE 工程服务的,它致力于实现 SLO 目标。建立可观测性不仅仅是运维团队的事情,更是整个开发、测试以及…...

100种思维模型之认知资源思维模型-030
我们常说,一个人永远也赚不到自己认知以外的钱,这话的确很有道理,被无数人所推崇。 由此,不难看出,认知在我们的生活起着多么关键的作用。 你的认知层次越高,范围越广,就意味着你这个人所处的阶…...

c/cpp - 多线程/进程 基础
c/cpp - 多线程/进程 基础1. 概念1.1 程序1.2 任务1.3 多任务1.4 进程1.5 线程1.5 线程/进程应用程序/系统资源并发/并行/同步/异步1. 概念 1.1 程序 代码、指令,静态的 1.2 任务 具体要做的实景,可以是基于进程、或基于线程 1.3 多任务 例如࿱…...

第55章 头像图片的前端渲染显示
1 WebApi.Controllers.CustomerController.GetCustomerByToken /// <param name"token">1个指定的令牌字符串。</param> /// <summary> /// 【通过令牌获取用户-无需权限】 /// </summary> /// <remarks> /// 摘要: /// …...

vue2 使用 cesium 【第二篇-相机视角移动+添加模型】
vue2 使用 cesium 【第二篇-相机视角移动添加模型】 搞了一阵子 cesium,小白入门,这东西很牛逼,但是感觉这东西好费劲啊!网上资料不多,每个人的用法又不一样,操作起来真的是绝绝子。之前写了一篇 vue2 使用…...

C/C++ 操作ini文件(SinpleIni 跨平台库)
最近在学习时,发现自己还不会操作ini文件,想着以前工作时接触到的项目或多或少都要用到ini文件去保存初始化程序的数据;所以赶紧去网上搜索以下C/C操作ini文件都有些什么库可以玩玩;搜索到有: 1. inih:这是…...
Cadence Allegro 导出Design Rules Check(DRC)Report报告详解
⏪《上一篇》 🏡《上级目录》 ⏩《下一篇》 目录 1,概述2,Design Rules Check(DRC)Report作用3,Design Rules Check(DRC)Report示例4,Design Rules Check(DRC)Report导出方法4.1,方法14.2,方法2B站关注“硬小...

Java的stream流
Java 8中引入的新特性,stream流通过与Lambda表达式结合,采用函数式编程,简化数组、集合操作,提高效率。 我们操作一个集合,就把他看作一个流,整个流依次执行,(可以类比为一个管道&a…...
Mybatis_相关配置解析和ResultMap
目录配置解析核心配置文件mybatis-config.xml 系统核心配置文件environments元素子元素节点:environmentmappers元素Mapper文件Properties优化typeAliases优化その他生命周期和作用域(Scope)方法作用域应用作用域方法作用域ResultMap提出问题…...
Python量化入门:利用中长期RSI寻找趋势拐点,抓大放小,蹲一个大机会!
一、RSI的原理 1. RSI简介 股票的涨跌说白了就是多空博弈造成的,多方力量更强则股票价格上涨,空方力量更强则股票价格下跌。那么我们如何来衡量股票的多空力量强弱呢? 上个世纪70年代,威尔斯威尔得发表了相对强弱指标,即我们常说的RSI(Relative Strength Index),RSI…...

案例14-代码结构逻辑混乱,页面设计不美观
目录 目录 一:背景介绍 二:思路&方案 三:过程 问题1:代码可读性差,代码结构混乱 问题2: 代码逻辑混乱,缺乏封装的意识 问题3:美观问题:问题和图标没有对应上 四…...

弱监督参考图像分割:Learning From Box Annotations for Referring Image Segmentation论文阅读笔记
弱监督参考图像分割:Learning From Box Annotations for Referring Image Segmentation论文阅读笔记一、Abstract二、引言三、相关工作A、全监督参考图像分割B、基于 Box 的实例分割C、带有噪声标签的学习四、提出的方法A、概述B、伪标签生成目标轮廓预测Proposal 选…...

Linux进程和任务管理和分析和排查系统故障
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...
【满分】【华为OD机试真题2023 JAVA】最多几个直角三角形
华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 最多几个直角三角形 知识点递归深搜 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 有N条线段,长度分别为a[1]-a[N]。现要求你计算这N条线段最多可以组合成几个直角三角形,每条线段只能使用一次,每个三…...

PyQt5可视化 7 饼图和柱状图实操案例 ②建表建项目改布局
目录 一、数据库建表 1 建表 2 插入数据 3 查看表数据 二、建立项目 1 新建项目 2 appMain.py 3 myMainWindow.py 4 myChartView.py 2.4.1 提升的后果 2.4.2 QmyChartView类说明 2.4.3 添加代码 三、修改myMainWindow.py程序,添加功能 1 打开数据库 …...

sonarqube指标详解
最近公司引入了sonar,作为代码质量检测工具,以期提高研发同学的代码质量,但是结果出来后,有些同学不清楚相应的指标内容,不知道应该重点关注哪些指标,于是查询了一下相关的资料,加以总结同时也分…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...