链接装载(一)虚拟地址与物理地址

news2024/11/16 0:50:54

文章目录

    • 一、基本概念
    • 二、一个基本问题
    • 三、程序的执行
    • 四、从堆中分配的数据的逻辑地址

一、基本概念

当我们写出一个程序,即便是最基本的 Hello World,都需要经过 预处理、编译、汇编、链接才能生成最终的可执行文件。

预处理:

预处理过程主要处理源代码中以 #开始的预编译指令,主要处理如下:

  • 将所有的 #define 删除,并展开所有宏定义
  • 处理所有的预编译指令,比如 #if、#ifdef、#endif等等
  • 处理 #include,将所包含的文件的内容插入到该指令位置,该过程递归进行
  • 删除所有注释
  • 添加行号和文件名标识

编译:

将预处理好的文件经过一系列的词法分析、语法分析、语义分析产生汇编代码

汇编:

将汇编代码转为机器指令

链接:

将不同的机器指令文件链接形成一个可执行文件

二、一个基本问题

我们在学习过OS之后,都知道进程拥有自己的虚拟地址空间,需要经过页表映射到物理地址空间。那么,计算机在真正执行代码的时候,是如何将一个变量与一个逻辑地址相关联起来的呢?

初步的理解是,程序在经过编译、链接之后,就已经以虚拟地址的形式存在了,因此操作某个变量的代码就转换成了操作该变量虚拟地址的机器指令。

那链接到底是什么呢?

随着程序的日益增大,程序被划分为很多个独立的模块,将不同的模块组合为一个完整的程序,实际上是模块之间的组合与通信。而模块间的通信方式一种是模块间的函数访问,一种是变量访问,而这两种都需要知道目标的地址,其实就是对某个符号的虚拟地址的寻找,即某个模块把对引用符号相关的逻辑转换为对其虚拟地址操作的过程。通俗的理解,这种寻找某个符号虚拟地址的过程就是链接。

链接的主要作用:地址和空间分配、符号绑定(地址绑定)、重定位

链接的目标是目标文件,目标文件经过编译、汇编产生。某个源文件编译时,已经将自身定义好的各种符号转换为了针对寄存器和地址偏移量的操作的序列(即汇编代码中并不存在我们定义的那些变量,而是转换为了各种寄存器和地址的读取存放操作,可以理解为对该符号虚拟地址的操作),但如果目标文件中有的符号来自其他目标文件,那么编译时无法为其生成偏移,因此会特殊标记,等链接的时候再将这个标记转换为对其虚拟地址的操作。(偏移量其实就相当于是虚拟地址)

因此产生另外一个问题,编译、链接的过程就已经完成虚拟地址的分配了吗?

初步理解是的,除了堆上malloc的(可能还有别的)一些需要运行时动态申请的内存的地址未定之外,其他的应该都已经在编译、汇编的过程中分配好了。malloc动态申请的也是一个固定区间内的,因为堆的大小和起始虚拟地址是确定的。

但是,这感觉还是有些别扭,不应该是程序在执行时,由OS分配虚拟地址空间,在加载程序的过程中为各种变量确定具体的虚拟地址吗? 如果提前在编译时虚拟地址就已经分配完毕,那如使用 mmap 预留一部分虚拟地址的操作是如何实现的呢?

我们从程序在OS上的具体执行过程中来寻找答案。

三、程序的执行

在OS上,我们运行一个程序,会创建一个对应的进程,然后加载可执行文件,执行其逻辑。此时OS要进行:

  • 创建独立的虚拟地址空间
  • 读取可执行文件头,建立虚拟地址空间与可执行文件的映射
  • 将CPU的指令寄存器设置为可执行文件的入口地址。

创建虚拟地址空间

创建虚拟空间其实只是创建一个页表,此时页表为空。整个页表表示进程的虚拟地址空间,因此可执行文件中的确定好的虚拟地址会放到对应的虚拟地址的页表项中。即进程的虚拟地址空间的地址和可执行文件的虚拟地址是等价的。

与可执行文件进行映射

可执行文件中,某个段的虚拟地址为 0x12345678,那么其对应进程虚拟地址空间的地址也是0x12345678。

因此可执行文件头部中包含main函数的虚拟地址,将程序加载后,将cpu的指令寄存器设置为 main 函数的虚拟地址,此时去查找页表,发生缺页中断,从磁盘中读取可执行文件的对应内容,然后开始执行main函数。

因此,编译好的可执行文件可以理解为从0x0虚拟地址开始编排,每个变量相对文件头的偏移量就是其虚拟地址。

OS创建虚拟地址空间,也是创建一个4G(假设32位)大小的空间,从0x0 开始和可执行文件一一对应,因此变量或者函数在可执行文件中的偏移量就是其在进程中的虚拟地址。所以,OS的创建的进程虚拟地址空间和可执行文件的虚拟地址是映像的关系。(其实也不是完全的等价,因为可执行程序通常很小,用不掉3G的空间,因此进程的虚拟地址空间只有一部分用来存储可执行文件,其余部分的地址要么没有使用,要么被当作堆等等)
在这里插入图片描述

因此程序的执行,可以看作将磁盘中的可执行文件拷贝到内存中,然后对可执行文件进行修修改改。

只是为了提高内存利用率,引入了页表。实现逻辑上将可执行文件全部拷贝到了内存中,但实际上只是拷贝了需要的部分到内存。

那此时mmap的疑问还是没有得到解答,mmap如果映射一段虚拟地址,但是这段虚拟地址是已经被使用的怎么办呢? 或者使用mmap预留一段虚拟地址,但这块虚拟地址对应数据段或者代码段怎么办?

其实这个问题应该是不存在的,每个进程会专门预留一个段空间,即一部分虚拟地址空间专门用来进行映射,因此mmap函数所使用的虚拟地址都在该区域内部。

从这里的我们也可以得知。mmap的原理就是创建新的页表项,并与某个文件关联。
在这里插入图片描述
那mmap函数调用的时候,传入一个addr,这个addr会在mmap调用内部进行判断,如果小于内存映射区域的最小地址,会将其改为当前可用的最小地址。

if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
        if (!(file && path_noexec(&file->f_path)))
            prot |= PROT_EXEC;
    /* 假如没有设置MAP_FIXED标志,且addr小于mmap_min_addr, 因为可以修改addr,
    所以就需要将addr设为mmap_min_addr的页对齐后的地址 */
    if (!(flags & MAP_FIXED))
        addr = round_hint_to_min(addr);

四、从堆中分配的数据的逻辑地址

在程序中,堆从某个地址开始,我们通过malloc等系统调用可以从堆中申请一个虚拟地址,那么这个虚拟地址我们是在程序运行时才会得知的,且该块虚拟地址并不会和可执行文件中的内容进行映射,因此需要通过read系统调用,从磁盘中读到内核,再由内核拷贝到该虚拟地址对应的物理地址中。所以,为了减少拷贝,才有了mmap。

而我们虽然只有在运行时才可以得到从堆中分配的内存的具体的虚拟地址,但是malloc返回的指针的虚拟地址我们是在编译时就可以确定的,只是其一开始的值为0,只有malloc调用之后,才会将分配内存的虚拟地址存储到该指针中,我们使用该指针,就间接的使用了这段内存。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring ioc的循环依赖问题

spring ioc的循环依赖问题什么是循环依赖spring中循环依赖的场景通过构造函数注入时的循环依赖通过setter或Autowired注入时的循环依赖循环依赖的处理机制原型bean循环依赖单例bean通过构造函数注入循环依赖单例bean通过setter或者Autowired注入的循环依赖三级缓存对象的创建分…

Metasploit 操作及内网 Pivot图文教程

目录 一、metasploit 简介 二、 基本使用 三、 使用 encoders 四、pivot 技术 一、metasploit 简介 Metasploit 是一款开源的安全漏洞检测工具,集成了丰富的渗透测试工具,深受安 全工作者喜爱。官方网站:www.metasploit.com 本案例将以图…

OS-调度

调度 多个程序在并发的情况下执行,最大化CPU利用率,同时要保证一定的公平性 调度的时机 五种情况: Running -> Waiting:例如等待I/ORunning -> Ready: interupt,计时器到时间了Running -> TerminatedWait…

我把Idea给改了,看看有没有你常用的功能,没有,你告诉我,我来改

改造的目标 时隔2个多月的研发,11月25日,终于把Idea插件BG-BOOM的1.1.0版本搞上线了,本次更新勇哥也是百忙之中挤时间,加班加点开发为粉丝,目的也主要是帮助大家提升开发效率,有更多摸鱼和内卷时间&#x…

[附源码]Python计算机毕业设计SSM晋中学院教室管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

QT中怎么设置定时器/周期任务/定时触发任务

Qt中定时器的使用有两种方法,一种是使用QObject类提供的定时器,还有一种就是使用QTimer类。 其精确度一般依赖于操作系统和硬件,但一般支持20ms。下面将分别介绍两种方法来使用定时器。 QObject类提供的定时器 QObject中的定时器的使用&am…

Makefile 详解

文章目录1.什么是Makefile2.Makefile文件命名规则3.编写Makefile4.Makefile 的工作原理5.Makefile中的变量6.模式匹配7.函数1.什么是Makefile 一个工程中的源文件不计其数,按期类型、功能、模块分别放在若干个文件中,MakeFile文件定义了一系列的规则来制…

HIN应用调研总结

文章目录1. 代码安全iDev: enhancing social coding security by cross-platform user identification between GitHub and stack overflow【A】2. API推荐Group preference based API recommendation via heterogeneous information network【A】3.Andorid恶意软件检测Out-of-…

SSM甜品店系统计算机毕业论文java毕业设计选题源代码

💖💖更多项目资源,最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之SSM甜品店系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygogogo.com/i…

中英双语多语言外贸企业网站源码系统 - HanCMS - 安装部署教程

随着跨境独立站的流行,中英双语的公司官网越来越受到重视。 此项目是基于开源CMS开发出的中英文双语外贸企业网站内容管理系统,命名HanCMS HanCMS 汉CMS中英双语多语种外贸网站系统,是一个轻量级的网站系统,访问速度极快&#xff…

[附源码]计算机毕业设计小太阳幼儿园学生管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

威伦触摸屏TK6060IP简单例子

详情见以下链接 https://download.csdn.net/download/weixin_39926429/87242438

[附源码]Python计算机毕业设计SSM教务管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析1. 厄尔尼诺海平面周期变化数据集介绍2. 基于连续小波变换的信号分析2.1 原始信号读取可视化2.2 傅里叶变换结果可视化2.3 小波变换结果可视化参考资料后记1. 厄尔尼诺海平面周期变化数据集介绍 这些数据是通过国际热带海洋…

文件上传的multipart/form-data属性,你理解了吗

form表单经常用于前端发送请求,比如:用户填写信息、选择数据、上传文件,对于不同的场景,上传数据的格式也会有些区别。 action action 表示该请求的 url 地址,定义在form上,请求的URI,可以写完…

【Python自然语言处理】文本向量化的六种常见模型讲解(独热编码、词袋模型、词频-逆文档频率模型、N元模型、单词-向量模型、文档-向量模型)

觉得有帮助请点赞关注收藏~~~ 一、文本向量化 文本向量化:将文本信息表示成能够表达文本语义的向量,是用数值向量来表示文本的语义。 词嵌入(Word Embedding):一种将文本中的词转换成数字向量的方法,属于文本向量化处理的范畴。 …

Linux操作系统~基于systemV共享内存的进程间通信

目录 一.进程间通信有哪些方式 二.什么是systemV 三.共享内存-双向通信-大致实现思路 四.4个函数about共享内存 1.shmget函数-创建 ftok函数 ​编辑 e.g. ipcs/ipcrm指令(ipc资源会被回收吗) 2.shmctl函数-删除/释放 3.shmat函数-挂接 4.shmdt…

汽车以太网简史

一、为啥需要新车载总线 在一个行业中,当一种新技术被开发和启用时,影响该技术成功的因素有很多。其中最重要的是该技术带来的益处以及自身成本。 第一个吃螃蟹的 2004年宝马决定从2008年起在其开始量产(SOP)的汽车中引入一个中…

c++ 指针

目录 1.指针的基本概念 2.定义指针,使用指针 3.指针所占的内存空间 4.空指针和野指针 4.1空指针 4.2野指针 5.const修饰指针 5.1常量指针 5.2指针常量 5.3const既修饰指针又修饰常量 6.指针和数组,利用指针访问数组 6.1概述 6.2使用数组名和下表访问 6.3使用…

【LIN总线测试】——LIN主节点数据链路层测试

系列文章目录 📒【LIN总线测试】——LIN主节点物理层测试 📒【LIN总线测试】——LIN从节点物理层测试 📒【LIN总线测试】——LIN主节点数据链路层测试 📒【LIN总线测试】——LIN主节点网络管理测试 📒【LIN总线测试】…