【Linux】第二十九站:再谈进程地址空间

这篇具有很好参考价值的文章主要介绍了【Linux】第二十九站:再谈进程地址空间。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、一些疑问

什么是虚拟地址?什么是物理地址?CPU读到的指令里面用的地址,是什么地址??

我们之前在使用动态库的时候,有一个选项-fPIC,它是与地址无关码。

二、程序没有加载前的地址(程序)

程序编译好之后,内部有地址的概念吗?

答案是有的!如下所示,其实在程序的内部,这些变量名都已经变成了地址了

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

在以前还没有虚拟地址的时候,我们的程序一开始还没有被执行的时候,它就已经会被分成各个段。

而现在这些编译时的编址已经是平坦模式[0,4GB]。即它在编址的时候已经严格按照地址空间的方式进行编译代码的。所以说在磁盘上看到的可执行程序的顺序排布和以后的进程地址空间中的规则是一样的。

所以编译器也已经考虑了操作系统了!!!

如下所示

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

这里的地址已经就是虚拟地址了!,也就是说可执行程序还没加载上去时候,已经是虚拟地址了,不过为了进行区分,在可执行程序还没有进行加载的时候,我们会把他叫做逻辑地址。如果是50多年前,逻辑地址和虚拟地址还是不一样的,不过现在逻辑地址,虚拟地址,线性地址等这些已经是同一个概念了,只不过逻辑地址一般是磁盘当中的可执行程序的地址

我们可以先随便写一点代码

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

然后编译运行以下

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

然后我们使用这个指令,这个指令可以直接将我们这个程序给反汇编出来

objdump -S a.out

比如下面的这一部分,左边的这一行就是每个指令的地址,每个指令都有不同的长度,有的是一个,有的是三个等等

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

三、程序加载后的地址

如下所示,当我们把代码和数据加载到内存的时候,当然要占据物理内存

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

从而天然的就有了物理地址,所以当可执行程序加载到内存的时候,就有了两套地址,一套是逻辑地址,一套是物理地址。

那么如何执行第一条指令呢?

其实在可执行程序中已经有一个entry入口地址了,那么这个entry是不是物理地址呢?其实不是,因为它是在加载之前就有了,它就是一个逻辑地址。

我们之气那也说过,一个进程是有自己的cwd工作目录和exe能找到自己的可执行程序的

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

当内核数据结构形成以后,我们可以将代码先加载到内存,当然也可以先不加载,我们这里先认为没有加载。它会先读取可执行程序的一些东西,将可执行程序的入口地址entry放到EIP/PC寄存器中。因为这个正好就是一个虚拟地址,所以就可以直接去正文代码中开始执行了,然后开始读取页表

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

然后此时我们现在的页表并没有建立映射,那么就会产生缺页中断,就会将程序加载进去,然后它也就天然具有了物理地址。最终虚拟物理地址的映射在页表中也都有了

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

然后就可以按照正常顺序去执行了。当我们读取到下面的那条函数调用指令的时候。

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

我们会发现,CPU内部读到的指令,内部可能有数据,可能也有地址,而这里的地址就是虚拟地址!,这里的虚拟地址还是需要经过页表转换成物理地址,然后继续执行。如果这虚拟地址不存在,那么直接缺页中断即可。

而此时,我们就发现了,我们的程序中,从读取到的第一个指令,到CPU的处理,再到二次继续访问它,用的全部都是虚拟地址

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

而这里其实就是编译器和操作系统相互协调的最重要的表现之一

四、动态库的地址

如下图所示

像这样的地址就是绝对地址

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

还有一种地址是相对地址,或者称作逻辑地址,比如下面的例子,有一个100米的跑道,有一颗树在40m处,那么当我们处于50m处的时候,我们可以说绝对地址是50,也可以说相对地址是10。

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

但是当这个树就在0处的时候,那么绝对地址就是相对地址或者逻辑地址

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

而在我们前面的可执行程序中,就是因为相对都是从0开始的,所以可以叫做逻辑地址,虚拟地址,相对地址这些

如下图所示,是我们前面已经提过的

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

现在当我们这个程序有一个printf时候,就需要调用动态库中的函数,然后它也要被加载到内存当中

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

现在我们的问题是:共享库大了,具体映射到哪里呢?

我们现在这个0x1122这个地址是一个线性地址,我们的程序要跳转到对应的位置,它在共享库中也必须在对应的位置,即0x1122,否则找不到。

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

所以它就必须得在固定地址处

但是这时候问题来了,一个进程可能要有十几个库,那么怎么能都加载到固定位置呢?

所以动态库被加载到固定地址空间中的位置是不可能的。

所以库要可以在虚拟内存中,任意位置加载!!!

所以库让自己内部函数不要采用绝对编址,只表示每个函数在库中的偏移量即可!!!

【Linux】第二十九站:再谈进程地址空间,【Linux】,linux,运维,服务器,算法,c语言,c++

这样的话,当代码要访问库中的方法时候,那么只需要起始地址+这个偏移量即可,从而进行对应找到代码

所以我们在前面说fPIC选项的时候,它是一个与位置无关码,意思就是直接用偏移量对库函数编址

静态库为什么不谈加载?不谈与位置无关?

因为静态库是直接被拷贝到可执行程序中的。就相当于库中的方法就是我们的方法。就直接用绝对编址进行编址了文章来源地址https://www.toymoban.com/news/detail-794993.html

到了这里,关于【Linux】第二十九站:再谈进程地址空间的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程周边006之进程地址空间

      👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.程序地址空间 1.1验证地址空间的排布  1.2利用fork函数观察当子进程修改某个共

    2024年02月04日
    浏览(41)
  • 【Linux】进程>环境变量&&地址空间&&进程调度

    主页: 醋溜马桶圈-CSDN博客 专栏: Linux_醋溜马桶圈的博客-CSDN博客 gitee :mnxcc (mnxcc) - Gitee.com 目录 1.环境变量 1.1 基本概念 1.2 常见环境变量  1.3 查看环境变量方法  1.4 和环境变量相关的命令 1.5 环境变量的组织方式 1.6 通过代码如何获取环境变量 1.6.1 命令行第三个参数 1

    2024年04月15日
    浏览(54)
  • 【Linux】深挖进程地址空间

    作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等 座右铭:松树千年终是朽,槿花一日自为荣。 目标:熟悉【Linux】进程地址空间 毒鸡汤:也许有一天,你发觉日子特别的艰难,那可能是这次的收获特别的巨大。 望小伙伴们点赞👍收藏✨加关注哟💕💕      

    2024年02月03日
    浏览(39)
  • Linux:进程地址空间

    目录 1.程序地址空间  2.进程地址空间 我们在讲C/C++语言的时候,32位平台下,我们见过这样的空间布局图 我们来验证一下这张图的正确性: 运行结果: 通过观察静态变量的位置,可以认为静态变量就是全局变量,只是静态变量只初始化一次,有作用域的限制。 这里栈区还

    2024年02月04日
    浏览(41)
  • 【Linux】—— 进程地址空间

    序言: 在上篇中,我们讲解了关于进程优先级的概念。本期,我将给大家介绍的是关于进程地址空间的话题。 目录 (一)程序地址空间回顾 (二)代码演示 (三)进程地址空间的引入 总结 我们在学习C/C++语言的时候,大家可能都见过这样的空间布局图: 一个程序有哪些

    2024年02月15日
    浏览(42)
  • 浅析Linux进程地址空间

    现代处理器基本都支持虚拟内存管理,在开启虚存管理时,程序只能访问到虚拟地址,处理器的内存管理单元(MMU)会自动完成虚拟地址到物理地址的转换。基于虚拟内存机制,操作系统可以为每个运行中的进程创建独享的虚拟地址空间,在这个空间中执行的程序,无法感知

    2024年01月20日
    浏览(39)
  • Linux--进程地址空间

    1.线程地址空间 所谓进程地址空间(process address space),就是从进程的视角看到的地址空间,是进程运行时所用到的虚拟地址的集合。 简单地说,进程就是内核数据结构和代码和本身的代码和数据,进程本身不能访问物理地址,之时候就需要有一个中间媒介,就是地址空间,

    2024年02月11日
    浏览(44)
  • 【Linux】理解进程地址空间

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 ​我们在学习C语言的时候,都学过内存区域的划分如栈、堆、代码区、数据区这些。但我们其实并不真正理解内存 — 我们之前一直说的内存是物理上的内存吗? 我们先看一段测试代码: 运行结果: 我们可以注意到子进程的变量

    2024年02月02日
    浏览(53)
  • 『 Linux 』进程地址空间概念

    在c/C++中存在一种 内存 的概念; 一般来说一个内存的空间分布包括 栈区 , 堆区 , 代码段 等等; 且内存是 自底向上 (由 0x00000000 至 0xFFFFFFFF ); 以该图为例: 该图即为常见的内存分布图; 正文代码段 正文代码段所存放的数据 一般为函数体的二进制代码 ; 已初始化数据区 已初始化

    2024年02月03日
    浏览(45)
  • 【Linux】进程理解与学习Ⅳ-进程地址空间

    环境:centos7.6,腾讯云服务器 Linux文章都放在了专栏:【 Linux 】欢迎支持订阅 🌹 相关文章推荐: 【Linux】冯.诺依曼体系结构与操作系统 【Linux】进程理解与学习Ⅰ-进程概念 浅谈Linux下的shell--BASH 【Linux】进程理解与学习Ⅱ-进程状态 【Linux】进程理解与学习Ⅲ-环境变量 在

    2023年04月14日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包