[Linux] Linux 初识进程地址空间 (进程地址空间第一弹)
标题:[Linux] Linux初识进程地址空间
个人主页@水墨不写bug
(图片来源于AI)
目录
一、什么是进程地址空间
二、为什么父子进程相同地址的变量的值不同
三、初识虚拟地址、页表
一、什么是进程地址空间
其实,在很久之前,也就是去年的时候,我在《C语言:动态内存规划》(可转跳的这篇文章)一文中,就提到了内存分布:不同的变量类型会存储在不同的内存区域。
但是这个内存真的是真正的内存吗?一个进程都有一个这样的内存区域吗?这样的内存区域是如何组织的?这是本文想要回答的问题。
我们在动态内存规划中讲解过,C/C++语言的不同变量存在于不同的区域:

但是,实际上我们对这个图片并没有非常只管的认识,我们只知道不同数据类型存储在不同的区域,我们甚至不知道这个整体的结构到底存储在哪里!接下来,一切都要从一个现象说起。
我们在Linux下,可以使用系统调用fork()创建一个子进程:

子进程的会"继承"父进程的代码和数据,所以我们可以通过一个if条件判断把父进程和子进程将要执行的代码分开:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int g_val = 0;int main()
{pid_t id = fork();if(id < 0)//返回值小于0,表示创建子进程失败,打印错误信息后返回{perror("fork");return 1;}else if(id == 0)//child子进程只能执行这里的代码{ printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);}else//parent父进程只能执行这里的代码{ printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(100);return 0;
}
上述的代码就通过if判断,把子进程和父进程将要执行的代码分离开,这样就能单独编写父子进程需要执行的任务了。
我们运行上面的代码,得到结果:

我们发现,父子进程的全局变量g_val的值是相同的,地址也是相同的!这符合我们的预期,因为子进程会按照父进程为模板,父子都没有对这个变量做出任何修改。
但是如果我们把这个代码稍微修改一下:(在子进程中故意修改全局的g_val变量)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int g_val = 0;int main()
{pid_t id = fork();if(id < 0){perror("fork");return 0;}else if(id == 0)//child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取{ g_val=100;printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);}else//parent{ sleep(3);printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(100);return 0;
}
这个时候再运行程序,得到结果:

这个结果发生了在语言层面上根本无法回答的问题:
同一个地址处的变量的值不相同!!
二、为什么父子进程相同地址的变量的值不同
其实,我们以前在C/C++中打印出来并看到的地址全都是虚拟地址,并不是真正的地址。
我们可以推测:
变量内容不一样,所以父子进程输出的变量绝对不是同一个变量。但地址值是一样的,说明,该地址绝对不是物理地址!
我们其实访问的都是虚拟地址,对于物理地址,用户一律是看不到的,是由操作系统统一管理的。于是操作系统负责讲把虚拟地址转化为物理地址。
具体如何操作呢?这就需要结合进程地址空间,同时,需要引入一个新的概念:页表。
三、初识虚拟地址、页表
页表,浅层次的理解,就是一个能把虚拟地址映射到物理地址的表。
操作系统通过PCB(也就是Linux的task_struct)来组织管理进程,进程地址空间本质是PCB内部的一个结构体,简单一点理解就是PCB内部含有维护本进程虚拟地址空间的信息:

在进程正常运行的情况下,PCB是链接在CPU的运行队列当中的:
这样,我们就对进程地址空间有了全新的直观的认识了。CPU会根据《Linux的O(1)调度算法来调度进程》(可转跳的这篇文章),这是之前的故事了,这里不再赘述。
言归正传,页表是一个把虚拟地址映射到物理地址的结构:

我们创建的全局变量g_val就存储在数据段,g_val自然会通过页表映射到一段物理地址:

当我们fork创建子进程,子进程会有和父进程一样的代码和数据:

但是,由于进程间具有独立性,所以注定子进程改变全局变量g_val不能影响到父进程:这就好比你写的代码遇到空指针挂了,你的VS不会跟着挂一样。
于是,解决这一问题的方法:写时拷贝就会发生。
当子进程想要该表父进程的g_val时,会发生写时拷贝,在物理地址空间上重新开辟一块空间,复制拷贝一份g_val专门给子进程使用,这在保证进程的独立性的同时也在最大程度上节约了空间资源。
到这里,你也许就会明白为什么相同的地址的值不同了:因为父子进程页表的内容是相同的。不同的是页表的映射关系不同了。
完~
未经作者同意禁止转载
相关文章:
[Linux] Linux 初识进程地址空间 (进程地址空间第一弹)
标题:[Linux] Linux初识进程地址空间 个人主页水墨不写bug (图片来源于AI) 目录 一、什么是进程地址空间 二、为什么父子进程相同地址的变量的值不同 三、初识虚拟地址、页表 一、什么是进程地址空间 其实,在很久之前…...
力扣21~25题
21题(简单): 分析: 按要求照做就好了,这种链表基本操作适合用c写,python用起来真的很奇怪 python代码: # Definition for singly-linked list. # class ListNode: # def __init__(self, v…...
04. prometheus 监控 Windows 服务器
prometheus 监控 Windows 服务器 1. 下载安装 Windows_exporter 安装包下载:https://github.com/prometheus-community/windows_exporter/releases 下载 msi 版本,上传至要监控的 Windows 服务器,双击安装即可,exporter 会自动…...
【机器学习】——决策树以及随机森林
文章目录 1. 决策树的基本概念与结构1.1 决策树的构建过程 2. 决策树的划分标准2.1 信息增益(Information Gain)2.2 信息增益比(Information Gain Ratio)2.3 基尼指数(Gini Index)2.4 均方误差(…...
怎么选择合适的数据恢复软件?适用于 Windows 的数据恢复软件对比
针对 Windows 的领先数据恢复软件的全面回顾: 丢失重要数据对任何 Windows 用户来说都是一场噩梦。从意外删除到系统崩溃,数据丢失是一个非常普遍的问题。值得庆幸的是,有强大的数据恢复工具可以帮助找回丢失的文件。这篇评论深入探讨了适用于…...
CI/CD 和 DevOps 工具概述:Jenkins 、Docker 的概述、工作流程、对比
随着软件开发的复杂性不断增加,持续集成(CI)、持续交付(CD)和运维(Ops)的概念逐渐成为现代软件开发流程中的核心组成部分。这些概念促进了开发团队与运维团队之间的协作,提升了软件的…...
基于SpringBoot+Vue+uniapp的高校教务管理小程序系统设计和实现
2. 详细视频演示 文章底部名片,联系我获取更详细的演示视频 3. 论文参考 4. 项目运行截图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 5. 技…...
如何在 Ubuntu VPS 上从 Apache Web 服务器迁移到 Nginx
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 在启动网站或应用程序时,您需要做出许多选择。有时,您的需求会发生变化,新技术变得可行&#x…...
pikachu靶场总结(一)
最近看到好多人还在打这个靶机所以把以前写的总结放上来了,主要是皮卡丘靶场漏洞的原理,利用方式,防护方法简略总结,纯手敲记录,总结如果不到位请评论区留言! 一、暴力破解 1.基于表单的暴力破解 原理&a…...
No.2 笔记 | 网络安全攻防:PC、CS工具与移动应用分析
引言 在当今数字化时代,网络安全已成为每个人都应该关注的重要话题。本文将总结一次关于网络安全攻防技术的学习内容,涵盖PC端和移动端的恶意程序利用,以及强大的渗透测试工具Cobalt Strike的使用。通过学习这些内容,我们不仅能够了解攻击者的手法,更能提高自身的安全意识和防…...
QD1-P8 HTML格式化标签
本节学习:HTML 格式化标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p8 一、font 标签 用途:定义文本的字体大小、颜色和 face(字体类型)。 示例 <!DOCTYPE html> <html><head><meta cha…...
WordPress修改固定链接后301的重定向方法
网站改版实际上是很忌讳的,尤其是针对已被搜索引擎收录的网站,新站不用考虑这些问题,而已经收录的网站网页在不遵守搜索引擎规则的前提下,是会被降权,关键词排名下滑、流量IP会被剥夺、收录会减少 、业务成交量会急剧下…...
关于Allegro导出Gerber时的槽孔问题
注意点一: 如果设计的板子中有 槽孔和通孔(俗称圆孔),不仅要NC Drill, 还要 NC Route allegro导出的槽孔文件后缀是 .rou 圆型孔后缀 是 .drl ,出gerber时需要看下是否有该文件。 注意点二: 导出钻孔文件时,设置参…...
平时使用的正则总结
1、将某一个字符串的后缀名后面加上“!400_500” 使用场景是将minio拿过来的图片压缩尺寸从而压缩其大小,加快渲染的速度。需要在图片的后缀名后面加上尺寸如下: const str //storage-test.test.shiqiao.com/gateway/common/isopen/2024/10/09/e708e9…...
[万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题
系列文章目录 使用transformers中的pipeline调用huggingface中模型过程中可能遇到的问题和修改建议 [万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题 文章目录 系列文章目录前言模型与数据集下载模型下载数据集下载 数据加载、…...
K8s简介及环境搭建
一、Kubernetes简介 kubernetes 的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能: 自我修复:一旦某一个容器崩溃&a…...
Python对PDF文件页面的旋转和切割
Python对PDF文件页面的旋转和切割 利用Python的.rotate()方法和.mediabox属性对PDF页面进行旋转和切割,最终生成一个PDF。下面结合案例进行说明,本示例中的名为split_and_rotate.pdf文件在practice_files文件夹中, 示例(1&#…...
Android 10.0 修改Systemui三键导航栏虚拟按键颜色功能实现
1.前言 在10.0的系统ROM定制化开发中,在对systemui的相关定制化开发中,在某些产品中,需要修改相关的 导航栏三键导航的虚拟按键的颜色,修改掉原来默认的虚拟按键的黑白色,接下来就来实现相关的功能 2.修改Systemui三键导航栏虚拟按键颜色功能实现的核心类 frameworks\ba…...
『网络游戏』客户端使用PESorket发送消息到服务器【14】
上一章服务器已经完成使用PESorket 现在我们将其导出在客户端中使用 生成成功后复制 粘贴到Unity项目中 进入Assets文件夹 粘贴两个.dll 创建脚本:ClientSession.cs 编写脚本: ClientSession.cs 编写脚本:GameStart.cs 将GameStart.cs脚本绑定在摄像机上 运行服务器 运行客户端…...
JVM(学习预热 - 走进Java)(持续更新迭代)
目录 一、彻底认识Java虚拟机 开创世纪:Sun Classic 开创世纪:Exact VM 武林霸主:HotSpot VM 移动端虚拟机:Mobile/Embedded VM “三大”其二:BEA JRockit/IBM J9 VM 软硬结合:BEA Liquid VM/Azul VM…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

