【Linux进程篇】进程地址空间(2)

【Linux进程篇】进程地址空间(2)

目录

  • 【Linux进程篇】进程地址空间(2)
      • 进程地址空间的再次理解
        • 什么是虚拟地址?fPIC与地址无关码是什么?为什么动态库里有,静态库里没有呢?

作者:爱写代码的刚子

时间:2023.11.21

前言:本篇博客将会介绍进程地址空间的深入理解。

进程地址空间的再次理解

继上一篇的动静态库,再次理解进程地址空间。

  • 动态库在进程运行的时候,是要被加载的(静态库没有)
  • 常见的动态库被所有的可执行程序(动态链接的),都要使用动态库——共享库

所以,动态库在系统中加载之后,会被所有进程共享,如何做到?(磁盘中的动态库在使用前先加载到物理内存,通过页表映射的方式映射到虚拟内存中的共享区

结论:建立映射,从此往后,我们执行的任何代码,都是在我们的进程地址空间中进行执行。

事实:系统在运行中,一定会存在多个动态库 ——OS管理(先描述再组织),系统中所有库的加载情况,OS非常清楚

  • 所以当存在另一个进程想要使用这个动态库时,操作系统会识别这个动态库有没有被加载到内存,如果已经加载到物理内存,直接通过页表映射到这个进程的共享区。

所以动态库也称为共享库,通过地址空间加自己的页表,将地址空间对应的库映射到自己的地址空间里。(如果存在全局变量,其中一个进程修改了它,则触发写实拷贝。数据一旦被多个人共享,它所在页的引用计数就会增加)

什么是虚拟地址?fPIC与地址无关码是什么?为什么动态库里有,静态库里没有呢?

谈谈地址


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

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

有的!(C++虚表)

程序在没有加载进内存的时候就已经被分成了很多段。(历史)

平坦模式(现在):按0~4GB将可执行程序编好,编译的时候就已经考虑了加载的问题。编译器也要考虑操作系统!

可执行程序在被编址的时候形成了**.code**(代码区)、.rdonly(只读数据区)、.data(已初始化的全局变量的一块内存区域)、.bss(存放程序中未初始化的或者初始值为0的全局变量的一块内存区域)已经是虚拟地址了,但是在可执行程序这里,程序还没有加载到内存,我们称这种地址为逻辑地址(磁盘当中我们程序形成时所对应的地址)。

  • objdump -S 可执行文件查看反汇编代码

在这里插入图片描述

  • 每个指令是有长度的,知道入口地址,加上每条指令都有长度,就能在逻辑上将代码跑起来。(所以指令的地址可以不用出现)

【问题】:CPU怎么知道指令的地址?CPU读到的指令里面用的地址,是什么地址?

CPU内置了指令集(精简指令集和复杂指令集)

重要的指令都会有两套地址:

(1)内部采用的,加载到内存之前的逻辑地址

(2)加载到物理内存时所具备的物理地址


  • 程序加载后的地址(进程)

可执行程序在编译形成的时候,它已经在可执行程序的头部,写好了entry(入口地址),不是物理地址,是逻辑地址,在内存中就叫虚拟地址。

CPU内存在EIP寄存器/PC指针。 task_struct进程里面存在cwd工作目录,也能找到自己的可执行程序。(先加载内核数据结构)读取可执行程序时,先将入口地址load到EIP寄存器中 。(可能会存在缺页中断),(虚拟地址加载好后每一条指令都天然具备物理地址,虚拟到物理填入页表中,映射关系建立好(4kb级别)),由于每条指令有大小,于是可以通过偏移执行下一条指令。

CPU内读取到的指令,内部可能有数据,也可能有地址(函数调用,函数的地址(虚拟地址)),找到对应的虚拟地址,转成物理地址(通过MMU硬件),再指向物理内存中指令的地址。同理,若页表中找不到对应的物理地址,则会再次发生缺页中断。整个过程中,凡是我们读到的地址都是虚拟地址。(指令间:虚拟地址,找到指令:物理地址)

虚拟地址到物理地址转换的知识扩展

编译器编译考虑地址空间,进程创建时也考虑地址空间,两者协同重要的表现之一。


  • 动态库的地址

可执行程序在调用某一动态库的函数时,需要将动态库加载到内存并建立映射,通过页表映射到共享库。

【问题】:共享库大了,具体映射到哪里呢?这个函数是采用绝对编址吗?

动态库被加载到固定地址空间中的位置是不可能的,库可以在虚拟内存中的任意位置加载。操作系统在动态库加载到内存的时候,操作系统会记住libc.so:start(起始地址),因为操作系统要对我们的库做管理(先描述再组织),所以一个库加载到了地址空间的什么地址,操作系统也需要知道并做管理。所以之后做库函数调用的时候,一旦识别到了库函数,跳转到共享区,找到对应动态库的起始地址,通过起始地址加偏移量的方式找到该函数。所以库函数内部不采用绝对编址,只表示每个函数在库中的偏移量(lib_start+偏移量,编译代码的时候就以符号的形式进行了实例化(这一块很复杂,可深挖))

  • ldd + 可执行程序显示调用的库

在这里插入图片描述


  • fPIC:产生位置无关码

gcc在编译时,直接用偏移量进行对库中函数进行编址

【问题】:静态库为什么不谈加载,不谈与位置无关?

静态库直接将代码拷贝到程序,静态库在进行编址的时候直接按照平坦模式,0~4GB,绝对编址按线性编好,所以不谈与位置无关码,静态库的函数地址是确定的。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/410404.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高考志愿填报系统开发技术语言选择总结

开发高考志愿填报系统,需要考虑到系统的稳定性、安全性、易用性以及数据准确性。以下是针对高考志愿填报系统的技术方案选择建议: 1.后端技术:可以使用Python、Java、PHP等后端语言进行开发,考虑到易用性和开发效率,可…

银行数据仓库体系实践(2)--系统架构

UML对系统架构的定义是:系统的组织结构,包括系统分解的组成部分,它们的关联性,交互,机制和指导原则,例如对系统群就是定义各子系统的功能和职责,如贷款系统群可能分为进件申请、核额、交易账务、…

C++力扣题目669--修剪二叉搜索树

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。…

iOS UI掉帧和卡顿优化解决方案记录

UI卡顿原理 在 VSync 信号到来后,系统图形服务会通过 CADisplayLink 等机制通知 App,App 主线程开始在 CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行…

JVM内存模型/运行时数据区域

java虚拟机管理这块内存,所以我们也叫运行时数据区域 总览 这里按线程是否共享来分类,所谓线程不共享就是每个线程里面都会配一套 程序计数器 栈, 互相不干涉。 而方法区和堆是线程所有共享 意味着只有一个(这里注意堆是实际概念…

数学建模-预测人口数据

目录 中国09~18年人口数据 创建时间 绘制时间序列图 使用专家建模器 得到结果 预测结果 残差的白噪声检验 中国09~18年人口数据 创建时间 路径:数据-> 定义日期和时间 绘制时间序列图 使用专家建模器 看看spss最终判断是那个模型最佳的契合 得到结果 预…

美国CEC能效认证测试简介

CEC能效认证测试简介 CEC是美国加利福尼亚州能源委员会(California Energy Commis-sions)的简称,它的职责是使能源市场朝着良性竞争的方向发展。该组织从1976年开始推行的加州电器能效法规(Appliance Efficiency Regul-ation&…

二叉树【Java】

文章目录 一、树型结构二、二叉树2.1概念2.2两种特殊的二叉树2.3二叉树的性质2.4二叉树的遍历 三、二叉树的基本操作3.1获取树中节点的个数3.2获取叶子节点的个数3.3获取第K层节点的个数3.4获取二叉树的高度3.5检测值为value的元素是否存在 一、树型结构 树是一种非线性的数据…

高级分布式系统-第10讲 分布式控制系统

高级分布式系统汇总:高级分布式系统目录汇总-CSDN博客 自动化是关于一切人造系统自动、智能、自主、高效和安全运行的科学与技术 计算机控制技术是实现自动化的主要方法和手段 分布式控制技术是伴随着机器大工业生产而诞生的特殊计算机控制技术 计算机控制系统 …

IC验证——perl脚本ccode_standard——c代码寄存器配置标准化

目录 1 脚本名称 2 脚本路径 3 脚本参数说明 4 脚本操作说明 5 脚本代码 1 脚本名称 ccode_standard 2 脚本路径 /scripts/bin/ccode_standard 3 脚本参数说明 次序 参数名 说明 1 address (./rfdig;.;..;./boot) 指定脚本执行路…

1-Docker-基础

本文内容多处参考黑马程序员的公开资料,仅用来个人梳理,原资料地址:https://b11et3un53m.feishu.cn/wiki/MWQIw4Zvhil0I5ktPHwcoqZdnec Docker介绍 为什么要用Docker? 以Mysql安装为例,想要在Linux系统上安装Mysql&…

Docker登录MySQL,密码正确却提示密码错误

当我输入了正确的MySQL密码的时候确提示我密码错误: ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES) docker run --name mysql_master \ -e MYSQL_ROOT_PASSWORD123123 \ -v /root/mysql_master/data:/var/lib/mysql \ -v /root…