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

Linux进程 --- 5(进程地址空间初识)

大家好今天我们将深入探讨进程地址空间的相关知识同时也会解答之前文章中遗留的一些问题。相信通过这篇文章的学习大家一定能有所收获历史问题引入在前面文章中我们介绍了fork函数有如下的形式pid_t id fork(); if (id 0) ... else if (id 0) ...通过不同的返回值去让父子进程执行不同的函数体但是我们有想过一些问题吗我们前面文章中讲过在return的时候会进行写入在这里发生了写时拷贝导致id的值不一样但是对于id来讲它就只是一个变量啊它既等于0又大于0了其实我们还是不能理解这是为什么对写时拷贝也不理解。接下来我们将通过对于进程地址空间的讲解就能够理解它了。C/C的内存整体布局在学习C/C时讲解变量类型时通常会提到不同变量存储在不同内存区域。栈区向下生长堆区向上生长局部变量具有临时性存储在栈区通过malloc和new申请的动态内存空间在堆区分配全局变量可被所有函数访问存储在全局变量区#include stdio.h #include stdlib.h int g_val_1; int g_val_2 100; int main() { printf(code addr: %p\n, main); const char* str hello c; printf(read only string addr: %p\n, str); printf(init global value addr: %p\n, g_val_2); printf(uninit global value addr: %p\n, g_val_1); char* mem (char*)malloc(100); printf(heap addr: %p\n, mem); printf(stack addr: %p\n, str); return 0; }通过上面的代码我们可以看到根据打印出来的不同地址我们就可以发现不同的变量是存储在不同的区域的#include stdio.h #include stdlib.h int g_val_1; int g_val_2 100; int main() { printf(code addr: %p\n, main); const char* str hello c; printf(read only string addr: %p\n, str); printf(init global value addr: %p\n, g_val_2); printf(uninit global value addr: %p\n, g_val_1); char* mem (char*)malloc(100); printf(heap addr: %p\n, mem); printf(stack addr: %p\n, str); int a; int b; int c; printf(stack addr: %p\n, a); printf(stack addr: %p\n, b); printf(stack addr: %p\n, c); return 0; }我们再次加入了几个局部变量看看是否栈区是向下生长的可以发现我们的栈区是向下生长的~#include stdio.h #include stdlib.h int g_val_1; int g_val_2 100; int main() { printf(code addr: %p\n, main); const char* str hello c; printf(read only string addr: %p\n, str); printf(init global value addr: %p\n, g_val_2); printf(uninit global value addr: %p\n, g_val_1); char* mem1 (char*)malloc(100); char* mem2 (char*)malloc(100); char* mem3 (char*)malloc(100); printf(heap addr: %p\n, mem1); printf(heap addr: %p\n, mem2); printf(heap addr: %p\n, mem3); printf(stack addr: %p\n, str); int a; int b; int c; printf(stack addr: %p\n, a); printf(stack addr: %p\n, b); printf(stack addr: %p\n, c); return 0; }随着堆空间申请内存地址就开始上升可以发现堆是向上生长的~#include stdio.h #include stdlib.h int g_val_1; int g_val_2 100; int main() { printf(code addr: %p\n, main); const char* str hello c; printf(read only string addr: %p\n, str); printf(init global value addr: %p\n, g_val_2); printf(uninit global value addr: %p\n, g_val_1); char* mem1 (char*)malloc(100); char* mem2 (char*)malloc(100); char* mem3 (char*)malloc(100); printf(heap addr: %p\n, mem1); printf(heap addr: %p\n, mem2); printf(heap addr: %p\n, mem3); printf(stack addr: %p\n, str); static int a; int b; int c; printf(a stack addr: %p\n, a); printf(stack addr: %p\n, b); printf(stack addr: %p\n, c); return 0; }我们来尝试一下将a改成static修饰的局部变量它的地址将变为什么可以发现加入static 后a变量的地址就变到跟全局变量挨着了这也就是为什么我们函数结束static修饰的局部变量生命周期还存在~但是问题来了这个东西就是内存吗其实不是这个是进程地址空间虚拟地址 线性地址前面我们再次复习了一下不同变量的存储在不同分区那么那个东西就是我们的内存吗其实不是的那个只是虚拟的地址空间通过下面这个代码就可以看出来了#include stdio.h #include stdlib.h #include unistd.h int g_val 100; int main() { pid_t id fork(); if (id 0) { // 子进程 int cnt 5; while(1) { printf(I am child, pid: %d, ppid: %d, g_val: %d, g_val: %p\n, getpid(), getppid(), g_val, g_val); if (cnt) cnt--; else{ g_val 200; printf(子进程change g_val: 100-200\n); cnt--; } sleep(1); } } else{ // 父进程 while(1) { printf(I am parent, pid: %d, ppid: %d, g_val: %d, g_val: %p\n, getpid(), getppid(), g_val, g_val); sleep(1); } } return 0; }我们通过子进程将g_val的值进行改变通过打印的结果当子进程将g_val的值改变以后后面打印父子进程打印的值却不一样可能就会想我们之前讲过写时拷贝啊两个已经被拷贝了所以打印的值不一样是正常的但是我们仔细观察它们的地址还是一样的啊一个物理地址能够存储不同的值怎么可能呢所以这个地址绝对不可能是真正的内存地址结论如果变量的地址是物理地址不可能存在上面的现象这个地址绝对不是物理地址这个地址叫做线性地址 或者 虚拟地址所以我们平时写的C/C用的指针指针里面的地址全部都不是物理地址进程地址空间问题解答系统在创建进程时不仅会为其建立PCB(进程控制块)这样的内核数据结构还会为每个进程分配一个独立的进程地址空间结构体。父进程的PCB中会通过指针来引用这个地址空间结构。进程的虚拟地址空间按照从0x00000000到0xFFFFFFFF的线性方式排列。此外系统还会为每个进程维护一个页表结构。页表采用键值对(key-value)的形式存储主要用于记录虚拟地址到物理地址的映射关系。内存空间分配完成后系统会为其分配物理地址。通过建立虚拟地址与物理地址的映射关系处理器可以根据页表将虚拟地址转换为物理地址从而访问存储在物理内存中的数据。此时父进程创建子进程时会复制一份相同的进程地址空间和页表。初始阶段子进程会完全继承父进程的页表映射关系。但当子进程需要修改变量值时系统会触发写时拷贝机制首先通过虚拟地址找到对应的物理地址若检测到需要修改数据则会在内存中重新分配空间建立新的虚拟地址到物理地址的映射关系。这样父子进程在查询变量地址时虽然看到的虚拟地址相同但实际映射的物理地址已经发生变化从而导致了变量值的差异。至此父子进程就实现了代码数据共享改变数据的时候写时拷贝重新开辟空间但是在这个过程中左侧的虚拟地址是0感知的不关心不会影响它~细节 - 进程地址空间本质地址空间解析1. 地址空间概念1.1 地址空间定义地址空间是指地址总线通过排列组合形成的地址范围表示为[0, 2^32]。1.2 地址空间区域划分区域划分实质上是通过定义起始(start)和结束(end)地址来划定内存范围超出该范围的访问将被视为非法。2. 32位系统的地址空间特性在32位计算机架构中32位的地址和数据总线意味着每条总线只能传输0或1信号地址组合总数可达2^32种由此决定的最大内存容量为4GB2^32 × 1byte3. 进程地址空间本质表示进程可访问的内存范围必须包含多个区域划分每个区域通过线性地址的start和end界定作为内核数据结构对象与PCB类似需要由操作系统统一管理struct mm_struct { long code_start; long code_end; long readonly_start; long readonly_end; long init_start; long init_end; long uninit_start; long uninit_end; long heap_start; long heap_end; long stack_start; long stack_end; ...... };在范围内连续的空间中每一个最小单位都可以有地址这个地址可以被使用4.为什么要有进程地址空间为进程提供统一的内存访问视图通过虚拟地址到物理地址的转换机制实现内存访问控制。该转换过程可进行地址合法性校验当检测到异常访问时立即拦截请求防止非法操作触及物理内存从而确保内存安全。通过页表的存在我们就可以完成进程管理和内存管理进行解耦合每个进程都维护着一个task_struct结构体其中包含指向进程地址空间的mm_struct* mm指针。当进程被CPU调度切换时这个地址空间信息会随进程上下文一起保存确保恢复时能够正确访问。对于页表管理CPU通过cr3寄存器存储当前页表的物理地址。在进程切换时cr3寄存器的值会被保存在对应的硬件上下文中待进程恢复执行时即可重新加载正确的页表信息。要确定进程访问的物理地址权限系统在页表中维护了一个权限位图rw。通过检查该位图中的读写标志位就能判断当前内存操作是否合法。这种机制有效防止了非法访问行为的发生。它确保了C/C语言中不同变量操作权限的合理分配页表中维护了一个标志位用于判断对应的代码和数据是否已加载到内存。在查询页表时首先需要检查该标志位。若发现标志位为0表示未加载到内存则会触发操作系统的缺页中断。因此进程创建时首先会初始化内核数据结构随后才加载对应的可执行程序。在此过程中只需创建进程地址空间和相应的页表即可。通过页表机制我们实现了进程管理与内存管理的有效解耦。结尾这篇文章深入浅出地讲解了进程地址空间的相关知识相信大家都能从中获益。希望大家能全面掌握进程地址空间、页表、虚拟内存和物理内存这些核心概念真正理解它们的原理与关联。点赞 收藏 关注❤️❤️❤️

相关文章:

Linux进程 --- 5(进程地址空间初识)

大家好!今天我们将深入探讨进程地址空间的相关知识,同时也会解答之前文章中遗留的一些问题。相信通过这篇文章的学习,大家一定能有所收获!历史问题引入在前面文章中我们介绍了fork函数,有如下的形式:pid_t …...

揭秘五轴数控磨床的坐标魔术:砂轮轴向如何随工件旋转?

在高端制造领域,五轴数控磨削机床是实现复杂曲面精密加工的核心装备。其魅力在于通过多轴联动,让砂轮与工件在三维空间中自由“共舞”,从而啃下叶轮、螺旋桨等硬骨头。然而,这场舞蹈的幕后指挥——坐标变换,却是一道让许多工程师头疼的数学谜题。今天,我们将深入拆解一个…...

Gitee本地项目上传及下载教程

1.Gitee仓库创建 ①登录Gitee官网,在首页右上角选择加号,点击新建仓库。 ②配置仓库 选择【初始化仓库】 ----【设置模板】----【选择分支模型】,其他的默认 注:【.gitignore一项,建议默认不选择状态】容易在本地项目上…...

Linux 进程控制(四)自主Shell命令行解释器.

目录 自主Shell命令行解释器 第1步 : 打印命令行字符串 第2步 : 从键盘中获取用户的字符串输入 第3步 : 解析命令行字符串 第4步 : 利用程序替换函数执行解析完的命令 第 5 步 : 内建命令的特殊处理 第6步 : 解析重定向命令 自主Shell命令行解释器 在前面学习完进程的创…...

在资源优化调度场景中,基于多源数据(如地磁/视频/雷达检测、浮动车GPS、手机信令、互联网地图API等)构建关联规则

在资源优化调度场景中,基于多源数据(如地磁/视频/雷达检测、浮动车GPS、手机信令、互联网地图API等)构建关联规则,可实现对城市交通系统的动态感知与协同优化。其核心逻辑包括:多源数据融合建模:通过时空对…...

基于VSG控制的MMC并网逆变器仿真模型(Simulink仿真实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

Ambari Metrics 是 Apache Ambari 提供的轻量级、嵌入式集群监控子系统,用于收集、聚合、存储和展示 Hadoop 生态组件

Ambari Metrics 是 Apache Ambari 提供的轻量级、嵌入式集群监控子系统,用于收集、聚合、存储和展示 Hadoop 生态组件(如 HDFS、YARN、HBase、Kafka 等)的关键性能指标(Metrics)。它基于时间序列数据库(默认…...

Apache Hadoop 生态系统(或与其深度集成)的企业级大数据平台核心服务,常见于 Hortonworks Data Platform(HDP)、Cloudera Data Platform

Apache Hadoop 生态系统(或与其深度集成)的企业级大数据平台核心服务,常见于 Hortonworks Data Platform(HDP)、Cloudera Data Platform(CDP)等发行版中,各自承担关键职能&#xff1…...

手机短信误删!4 个实用恢复方法,一文看懂轻松

你是否有过这样的懊恼时刻:手滑删除了银行的验证码短信,或是亲友的珍贵问候,急需时才发现信息已消失无踪?其实,被删除的短信并不会立刻从手机中彻底清除,只是被系统标记为 “可覆盖空间”—— 这个特性为恢…...

每天了解几个MCP SERVER:工具百宝箱!200+应用集成,Composio 让 AI 连接一切

每天了解几个MCP SERVER:🔧 Composio来源: https://docs.composio.dev/docs/mcp-overview简介 Composio MCP Server 提供200工具集成平台,让AI可以连接各种第三方应用和服务。 能做什么 工具集成:200应用集成工作流编排&#xff1…...

每天了解几个MCP SERVER:云端媒体库!AI 自动处理图片视频,Cloudinary 让媒体管理更简单

每天了解几个MCP SERVER:🖼️ Cloudinary来源: https://github.com/cloudinary/mcp-servers简介 Cloudinary MCP Server 提供云端图片管理和CDN服务,让AI可以进行图片上传、处理和优化。 能做什么 图片上传:上传图片和视频图片处理…...

每天了解几个MCP SERVER:极速分析神器!亿级数据秒级查询,ClickHouse 让大数据分析飞起

每天了解几个MCP SERVER:⚡ ClickHouse来源: https://github.com/ClickHouse/mcp-clickhouse简介 ClickHouse MCP Server 为AI Agent提供ClickHouse列式数据库的查询能力,以极高的性能分析大数据。 能做什么 SQL查询:执行高性能SQL查询实时分…...

刷题笔记:力扣第48题-旋转图像

1.拿到这道题目,第一反应是再创建一个新的矩阵,按照顺时针旋转90的方式遍历原来的矩阵,将旋转后的矩阵存入新矩阵中,输出即可。这种方法的时间复杂度和空间复杂度均为O(n2)。2.但本题不允许使用新的矩阵,这意味着一切修…...

OpenClaw使用教程 + 获取API + 踩坑

新手建议:如果研究不下去,直接用第三方的Oneclaw,字节、阿里、腾讯出品的第三方。 可以等一等,国产有替代。 别焦虑,没用,23年gpt,24年sora,25deepseek和agent,26开年o…...

免费查AI率完全攻略:5种不花钱的检测方法

免费查AI率完全攻略:5种不花钱的检测方法 写完论文之后最怕什么?不是导师让你改格式,而是交上去才发现AI率高得离谱。现在各高校对AI率查得越来越严,知网、维普、万方都上了AIGC检测模块,一旦被标记"疑似AI生成&q…...

免费降AI率软件排行:从白嫖到付费怎么选

免费降AI率软件排行:从白嫖到付费怎么选 写这篇文章的起因是,上个月有三个不同的朋友问了我同一个问题:“有没有免费降AI率的软件?” 一个是大四写毕业论文的,一个是在读研二准备投期刊的,还有一个是帮老板…...

毕业论文免费查AI率+降AI率一站式攻略

毕业论文免费查AI率降AI率一站式攻略 答辩季快到了,论文的事情一件接一件。查重过了还有AI检测,AI检测过了还有格式审查,感觉毕业比入学还难。 这篇文章解决一个具体问题:怎么用免费工具完成论文AI率的检测和修改。从"查出来…...

免费降ai工具实测:哪个免费额度最良心

免费降ai工具实测:哪个免费额度最良心 网上但凡说"免费"两个字的工具,十个里有八个是标题党。要么注册完发现免费额度只有100字,跟没有一样;要么做一堆任务才能解锁,转发三个群、邀请两个好友,折…...

HJ132 小红走网格

中等 通过率:31.75% 时间限制:1秒 空间限制:1024M 知识点数论 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。 描述 在二维平面坐标系中,小红初…...

2026 学术诚信必备!10 款 AI 论文查重工具盘点:查重 + AI 率双检测,告别毕业 / 投稿焦虑

又到本科毕设、期刊投稿的关键节点,「重复率飘红」「AI 率超标」成了悬在每一位学术人头顶的达摩克利斯之剑。传统查重工具只能检测文字重复,面对 AI 生成内容却束手无策;而专业 AI 检测又价格高昂、操作繁琐。 今天为大家整理了10 款兼顾查…...

在服务器上通过git仓库进行多开发者协同工作

本文旨在解决一个需求:在同一服务器上的若干个开发人员能够在自己的账户下面抓取和更新一个项目文件夹。1.首先是root权限创建git仓库:创建用于共享的裸仓库:git clone --bare 项目文件夹名 项目文件夹名.git创建用户组:sudo grou…...

C语言程序设计第四版(何钦铭、颜晖)第八章指针之拆分实数的整数与小数部分

1. 拆分实数的整数与小数部分:要求自定义一个函数 void splitfloat (float x, int* intpart,float *fracpart);其中x是被拆分的实数,*intpart和*fracpart分别是将实数x拆分出来的整数部分与小数部分。编写主函数,并在其中调用函数splitfloat()。试编写相应程序。#include<st…...

苍穹外卖WebSocket连接问题

在调试过程中发现&#xff0c;当前端应用部署在Nginx下访问localhost时&#xff0c;WebSocket连接无法建立&#xff1b;而直接运行前端项目时则可以正常连接。通过浏览器F12排查问题后&#xff0c;发现是WebSocket的URL路径不同&#xff1a;我们实际需要的地址为ws://localhost…...

c++ 类和对象(全)

本文只是把之前上中下三篇文章集合了起来&#xff0c;后面跟着补充一点示例代码&#xff0c;也只是为了方便大家一下子全部观看。 类和对象&#xff08;上&#xff09; 一.类的定义 1.类定义格式 我们可以先看一个类的例子(栈)&#xff1a; class Stack { private:int* a;in…...

优化Docker镜像下载速度:国内镜像源配置指南

1. 为什么需要配置国内Docker镜像源 第一次用Docker拉取镜像时&#xff0c;看着进度条像蜗牛一样缓慢移动&#xff0c;我盯着屏幕足足等了半小时。后来才发现&#xff0c;默认的Docker Hub服务器在国外&#xff0c;国内直接访问速度感人。这就像你在北京点外卖&#xff0c;却非…...

学生专属福利:如何免费获取JetBrains和Navicat全家桶

1. 学生专属福利&#xff1a;为什么你需要它们&#xff1f; 还在为开发工具的高昂费用发愁吗&#xff1f;作为一个过来人&#xff0c;我太懂学生时代那种“想学技术&#xff0c;却被工具卡住”的窘迫了。一套正版的JetBrains全家桶&#xff08;比如IntelliJ IDEA、PyCharm、Web…...

Markdown写作技巧:LaTeX公式+代码块高亮全攻略

Markdown写作技巧&#xff1a;LaTeX公式代码块高亮全攻略 在技术文档和学术研究的写作中&#xff0c;Markdown因其简洁性和强大功能已成为首选工具。但对于需要表达复杂数学公式或展示多语言代码的专业作者来说&#xff0c;如何充分利用Markdown的高级功能仍是一个挑战。本文将…...

基于PEX88096的PCIe 4.0八盘M.2扩展卡设计

1. 项目概述PCIe 4.0 M.2扩展卡长期面临市场定价畸高问题&#xff0c;主流商用产品普遍标价数千元&#xff0c;严重制约了高性能存储系统在DIY、边缘计算及小型服务器场景中的普及应用。本项目以PEX88048 PCIe 4.0交换芯片为核心&#xff0c;构建一款支持8路独立M.2 NVMe插槽的…...

Python+Selenium实现抖音博主批量监控:300+账号实时更新通知(附完整代码)

PythonSelenium构建高可用抖音博主监控系统&#xff1a;从零到一的实战架构与性能调优 最近在技术社群里&#xff0c;经常看到有朋友在讨论如何批量追踪抖音博主的更新动态。无论是做内容分析、竞品研究&#xff0c;还是个人兴趣追踪&#xff0c;手动刷新几百个主页显然不现实。…...

告别数据孤岛:基于WebDAV的Zotero与InfiniCLOUD跨平台同步实战

1. 为什么需要跨平台文献同步&#xff1f; 作为一名常年泡在实验室的研究生&#xff0c;我经历过无数次这样的崩溃瞬间&#xff1a;在实验室电脑上整理好的文献库&#xff0c;回到宿舍打开笔记本发现参考文献全乱了&#xff1b;出差路上想用平板查篇论文&#xff0c;却发现最新…...