Linux系统编程:进程地址空间

linux系统编程:进程地址空间一,内存地址空间1.1,栈区存储变量:普通局部变量、指针变量、函数参数、函数返回地址、临时变量、寄存器变量;

函数参数:函数的参数是从右到左依次入栈的;

Linux系统编程:进程地址空间在vs2022上栈区并不是”向下生长的”,而是正常的栈,因此推断结果应该是b的地址较低,a的地址比b的地址高;

Linux系统编程:进程地址空间函数返回地址:函数返回地址是指函数执行完毕后,程序需要跳转回继续执行的内存地址(即函数的地址)。当一个函数被调用时,当前程序的执行流程会转移到该函数内部。在函数执行完成后,程序需要知道回到哪里继续执行后续的代码,这个“回去的位置”对应的内存地址就是函数返回地址。

1.2,堆区介绍

立即进入“豆包AI人工智官网入口”;

立即学习“豆包AI人工智能在线问答入口”;

特点

动态分配:程序运行时可根据需要随时在堆区申请和释放内存空间,大小可在运行时确定,适应不同数据结构和算法的需求;

空间较大:一般来说,堆区的空间比栈区的空间更大,因为它是随机开辟的,并不像栈区地址都是连续的,所以空间更大,方便使用;

管理复杂:需要程序员手动管理内存分配和释放,容易引发悬空指针和由于忘了释放内存造成的内存泄漏问题;

1.3,全局区(数据段)与常量区全局区也称为静态存储区,用于存放全局变量和静态变量;

生命周期:随着进程结束释放内存;即便是函数内部的局部静态变量生命周期依旧是整个进程;

Linux系统编程:进程地址空间我们可以看到即便是超出了作用域,static int a 的地址空间依旧没有释放;这说明静态局部变量的生命周期不是随作用域的,而是随进程的;但只能在作用域中使用(在不返回值的情况下); ——>静态局部变量相当于全局变量,唯一的区别就是作用域不同;

1.4,代码段数据段是进程中存储执行代码的内存区域,它包含了程序的指令和常量(“1”,”hello world”….);

二,fork的遗留问题为什么fork有两个返回值?

这其实是在两个进程中看,父进程执行到fork时还没来得及return,此时子进程就已经创建出来了,并且也会return一个值,所以有两个值;那这么看就会产生两个数据,对吧;接下来我们验证一下他们的地址;

Linux系统编程:进程地址空间Linux系统编程:进程地址空间我们可以看到id的值是不一样的,但地址确实一样的,这是为什么呢?按道理说,如果地址相同那同一个地址怎么可能存两个数据呢?况且还发生了写时拷贝,地址怎么会相同呢?

其实这里我们看到的是虚拟内存地址;

先来解释一下上面的情况:

—->父进程创建子进程时确实发生了写时拷贝,id变量的确有两份,不过是写时拷贝开辟的空间是物理内存,这个时候物理内存上存在两个id地址,一个是父进程的,一个是子进程的,而我们在程序中看到的是虚拟内存地址;物理内存无法在程序中看到;

问题一:为什么要有虚拟地址(进程地址空间)

1.统一进程视角看待内存

现在我们使用OS类比一个大富翁,3个进程类比3个他的孩子;一个大富翁(操作系统)有10亿美金,而他有四个私生子,但是四个私生子(进程)都并不知道对方的存在(进程独立性),所以他们都认为大富翁只有他唯一一个儿子,而大富翁告诉他们一旦自己去世了,就把所有的家产留给他,所以每个儿子也都信了,因此大富翁其实给每个私生子都画了一个大饼(进程地址空间)。每个人都认为自己有十亿家产。但实际上是这些私生子要多少才会给多少(进程需要多少空间操作系统就给多少空间

如果有一张虚拟内存,这样每个进程就不需要关心当前的物理内存会不会影响到别的进程,我用的时候直接告诉OS,然后他帮我们分配,这样可以更加方便有序的使进程运行;

2.保护内存地址,出现问题直接拦截(相当于加了一层防护)

当我们申请物理内存空间时,就会利用虚拟地址进行地址审查,在这个转化过程中,如果虚拟内存地址出现问题,就会直接结束这个过程,就不会直接影响到物理内存;

为什么我们无法修改常量字符串?

常量字符串位于常量区域,但仅仅如此不足以说明不可修改,我们都知道不可修改是一种权限,那这个权限在哪里呢?其实这个权限是在页表中,当通过虚拟地址访问物理地址时,会通过页表转化并检查权限,如果没有权限就会被拦截;

三,什么是进程地址空间我们知道要管理一个对象的方法是–>先描述再组织;

Linux系统编程:进程地址空间四,页表现代操作系统不做浪费时间和空间的事;

4.1,写时拷贝,缺页中断,惰性加载首先,页表中有什么呢?

Linux系统编程:进程地址空间答:虚拟地址、物理地址、权限位、标志位(是否将对应的代码和数据加载到内存中)

权限位有什么用?

权限位上有该地址的读和写权限,如果该地址是只读权限那么我们对地址进行修改就会被OS直接拦截,非法请求就不会发送到物理内存,对物理内存起到一定程度的保护作用;

标志位是什么?

标志位是检查进程该地址需要的代码是否加载到了内存中;

惰性加载:就是需要多少加载多少,操作系统对于大文件是可以实现分批加载的,也就是进程可能有时会只有PCB在内存中;

缺页中断:当所需的代码和数据还没有被加载进内存的时候,这时候就会发生缺页中断,中断的意思就是暂时暂停此进程,等待代码和数据加载进来后就会继续执行进程;

那么为什么不一次性将代码数据加载到内存中呢?

从空间的角度思考,一个大文件加载是需要占用很大的空间的,而且进程一开始也不会马上用到一整块代码,所以这个时候有一些代码数据是空闲的,也就占用了额外的内存空间;

从时间的角度考虑,加载一个大文件十分耗费时间;一次性加载效率不高;

因此出现了缺页中断,其用意就是对代码和数据进行局部性加载,合理使用内存从而提高效率;

写时拷贝:数据段(全局区)的数据本来是可写的,但权限确实只读的,这么做的目的就是为了维持写时拷贝;当进程双方中的一方对数据进行修改,就会触发写时拷贝机制,重新开辟一块空间,存储新的数据,并且修改页表映射;

4.2进程地址是如何被切换的Linux系统编程:进程地址空间进程PCB结构体里有对应的进程地址空间指针,所以进程切换就意味着进程空间地址空间被切换,而页表会被存储在CPU的cr3寄存器中,这其实属于进程的上下文信息,在进程切换的时候会被进程带走,后面再恢复过来!

4.3进程创建的具体分析过程进程被创建的时候,优先被创建和加载的是PCB数据结构和对应的地址空间,代码和数据等到需要的会后在加载进来;

4.4重新理解进程具有独立性1.在PCB数据结构上,每一个进程都有自己唯一的PCB;

2.虚拟地址可以相同,但通过页表映射的物理地址是不同的;各自有各自的区域,对于父子进程在写时拷贝的机制下,也是拥有自己独一份的物理地址;

五,命令行参数和环境变量在栈的上面Linux系统编程:进程地址空间Linux系统编程:进程地址空间

以上就是Linux系统编程:进程地址空间的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/72791.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
归环回溯玩法怎么玩 归环时间循环机制详解
上一篇 2025年11月13日 18:30:38
free一个合法的地址也会导致crash?
下一篇 2025年11月13日 18:32:40

相关推荐

  • composer require-dev和require有什么不同_Composer Require与Require-Dev区别解析

    require用于声明项目运行必需的依赖,如框架、数据库组件和第三方SDK,这些包会随项目部署到生产环境;2. require-dev用于声明仅在开发和测试阶段需要的工具,如PHPUnit、PHPStan、Faker等,不会默认部署到生产环境;3. 安装时composer install根据环境决定…

    2026年5月10日
    900
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • 修复点击时按钮抖动:CSS垂直对齐实践

    本文探讨了在Web开发中,交互式按钮(如播放/暂停按钮)在点击时发生意外垂直位移的问题。通过分析CSS样式变化对元素布局的影响,我们发现这是由于按钮不同状态下的边框样式和内边距改变,以及默认的垂直对齐行为共同作用所致。核心解决方案是利用CSS的vertical-align属性,将其设置为middle…

    2026年5月10日
    000
  • 理解编程指令:当结果正确,但实现方式不符要求时

    本文探讨了在编程实践中,即使程序输出了正确的结果,但若其实现方式未能严格遵循既定指令,仍可能被视为“不正确”的问题。我们将通过具体示例,对比直接求和与累加求和两种实现策略,强调理解和遵守编程规范的重要性,以确保代码的健壮性、可维护性及符合项目要求。 在软件开发过程中,我们经常会遇到这样的情况:编写的…

    2026年5月10日
    000
  • php常量怎么用_PHP常量(define/const)定义与使用方法

    PHP中可通过define函数和const关键字定义常量,用于存储不可变值。define适用于全局作用域,支持动态名称和条件定义,如define(‘SITE_NAME’, ‘MyWebsite’);const在编译时生效,语法简洁但限制多,只能在类或全…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • Discord.py 交互按钮超时与持久化解决方案

    本教程旨在解决Discord.py中交互按钮在一段时间后出现“This Interaction Failed”错误的问题。我们将深入探讨视图(View)的超时机制,并提供通过正确设置timeout参数以及利用bot.add_view()方法实现按钮持久化的具体方案,确保您的机器人交互功能稳定可靠,即…

    2026年5月10日
    000
  • JavaScript 闭包:理解闭包原理与内存泄漏问题

    闭包是函数访问其外部作用域变量的能力,即使外部函数已执行完毕。如 inner 函数引用 outer 中的 count,形成闭包,使变量持久存在。闭包本身无害,但可能因延长变量生命周期导致内存泄漏,例如事件监听器引用大对象时。若未及时清理 DOM 事件或定时器,闭包会阻止垃圾回收,造成内存占用过高。解…

    2026年5月10日
    000
  • c++如何实现UDP通信_c++基于UDP的网络通信示例

    UDP通信基于套接字实现,适用于实时性要求高的场景。1. 流程包括创建套接字、绑定地址(接收方)、发送(sendto)与接收(recvfrom)数据、关闭套接字;2. 服务端监听指定端口,接收客户端消息并回传;3. 客户端发送消息至服务端并接收响应;4. 跨平台需处理Winsock初始化与库链接,编…

    2026年5月10日
    000
  • 谷歌浏览器如何截图 谷歌浏览器页面截图技巧

    谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧

    使用谷歌浏览器的开发者工具截图步骤:1. 按ctrl+shift+i(windows/linux)或cmd+option+i(mac)打开开发者工具。2. 点击右上角三个点,选择”更多工具”,再选择”截图”。3. 选择截取整个页面。推荐的谷歌浏览器扩展…

    2026年5月10日 用户投稿
    100
  • JS如何实现迭代器?迭代器协议

    JavaScript中实现迭代器需遵循可迭代协议和迭代器协议,通过定义[Symbol.iterator]方法返回具备next()方法的迭代器对象,从而支持for…of和展开运算符;该机制统一了数据结构的遍历接口,实现惰性求值,适用于自定义对象、树、图及无限序列等复杂场景,提升代码通用性与…

    2026年5月10日
    000
  • Golang使用Protobuf定义接口与消息格式

    Protobuf通过字段编号实现兼容性,新增字段可忽略、删除字段可保留编号,确保新旧版本互操作,支持服务独立演进。 在Golang项目中,利用Protobuf定义接口和消息格式,本质上是为服务间通信构建了一套高效、类型安全且跨语言的契约。它让数据结构清晰可见,RPC调用标准化,极大地简化了分布式系统…

    2026年5月10日
    000
  • Go语言接口与切片:如何识别和操作[]interface{}

    本文将深入探讨Go语言中如何识别和操作`[]interface{}`类型的切片。我们将介绍类型断言(Type Assertion)的关键作用,并通过`switch`语句演示如何安全地检测`[]interface{}`类型,并进而遍历其内部元素。文章旨在提供清晰的示例代码和专业指导,帮助开发者有效地处…

    2026年5月10日
    000
  • JavaScript 高效判断页面所有复选框状态的技巧与实践

    本文旨在提供一套高效且专业的javascript方法,用于判断网页中所有复选框的选中状态。我们将探讨如何利用`array.some()`快速确定是否有未选中的复选框(进而判断是否全部选中),以及如何使用`array.filter()`统计选中和未选中的复选框数量。通过优化dom元素选择和数组操作,提…

    2026年5月10日
    000
  • pycharm解析器怎么添加 解析器添加详细流程

    在pycharm中添加解析器的步骤包括:1) 打开pycharm并进入设置,2) 选择project interpreter,3) 点击齿轮图标并选择add,4) 选择解析器类型并配置路径,5) 点击ok完成添加。添加解析器后,选择合适的类型和版本,配置环境变量,并利用解析器的功能提高开发效率。 在…

    2026年5月10日
    000
  • 硬盘数据被误删除怎么办?教你快速找回删除的文件!

    硬盘数据被误删除,别慌!恢复数据并非不可能,关键在于你接下来的操作。立刻停止对该硬盘的任何写入操作,然后尝试使用专业的数据恢复软件。 解决方案 首先,数据恢复的原理是,删除文件后,操作系统只是将文件占用的空间标记为“可覆盖”,但文件本身的数据可能还存在于硬盘上。所以,避免新的数据写入覆盖掉旧数据,是…

    2026年5月10日
    000
  • c++中头文件和源文件的区别_c++头文件与源文件作用对比

    头文件声明接口,源文件实现逻辑。头文件含类、函数声明及宏定义,通过#include被多文件共享,用include守卫防重;源文件实现具体功能,编译为目标文件后由链接器合并。声明与实现分离提升模块化与编译效率,模板和内联函数因需编译时可见故常置于头文件,命名空间避免符号冲突,整体结构使项目更清晰易维护…

    2026年5月10日
    000
  • HTML文档的基本结构是什么? 3分钟带你了解HTML文档基础框架

    html文档的基础结构由四部分组成:1. 声明,用于告知浏览器以html5标准模式解析页面,避免怪异模式导致的兼容性问题;2. 根元素,包裹整个文档内容,并可通过lang属性指定语言;3. 头部区域,包含元数据如设置字符编码、实现响应式布局、定义页面标题、引入css和favicon、加载脚本等;4.…

    2026年5月10日
    000
  • Android和iOS系统下,HTML+JS代码运行结果差异:为什么input宽度为0时,Android输入方向异常?

    Android和iOS系统HTML+JS代码运行差异分析:input宽度为0引发的Android输入方向异常 开发OTP输入组件时,我们发现一个有趣的现象:当input元素的宽度设置为0 (style=”width: 0;”)时,Android系统下的输入方向会异常,而iOS系统则正常工作。 移除w…

    2026年5月10日
    000
  • Python官网用户调查的参与方式_Python官网反馈提交详细教程

    答案是通过访问Python官网新闻页面、邮件邀请链接或GitHub仓库提交反馈。具体为:访问官网查找用户调查公告,或点击邮件中的专属链接参与,在GitHub的cpython仓库提交技术建议,并注意如实填写问卷与保护隐私。 如果您希望参与Python官网的用户调查并提交反馈,可以通过官方指定的渠道完成…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信