《程序员的自我修养》阅读笔记

news2024/12/20 16:03:59

文章目录

  • 【第2部分】静态链接
    • 1 编译过程
    • 2 编辑器的工作流程
    • 3 链接——模块的拼接
    • 4 目标文件
      • 目标文件中的段(section)
      • ELF文件结构
    • 5 静态链接
      • 1 空间与地址分配
      • 2 符号解析与重定位
  • 【第3部分】装载与动态链接
    • 1 装载的方式
    • 2 进程的启动
    • 3 为什么需要动态链接?
    • 4 动态链接的基本实现
    • 5 位置无关码(PIC)
    • 6 显式运行时链接(Explicit Run-time Linking)

【第2部分】静态链接

在这里插入图片描述

1 编译过程

  1. 预编译
    预编译将源文件和包含的头文件编排成xx.i的预编译文件,主要是将#include的文件内容替换进源文件,并且将宏定义(#define)展开,还有处理预编译指令(#if#ifdef等)以及删除注释等等。
  2. 编译
    简单来说就是将C语言代码转换成汇编代码;
  3. 汇编
    汇编器将汇编代码转换成机器码,产出一个xx.o目标文件;
  4. 链接
    对目标文件进行编排,组合成可执行文件或者库(目标文件的包)。

2 编辑器的工作流程

词法分析->语法分析->语义分析->源代码优化->目标代码生成和优化。

3 链接——模块的拼接

问题引入:当一个程序被分割成多个模块时,最终如何组成的一个可执行程序?

链接的过程包括:

  • 地址和空间分配
  • 符号决议(symbol resolution),或符号绑定(symbol binding)
  • 重定位(relocation)——给程序中引用某个绝对地址的指令打补丁

链接器会根据指令所引用的符号,找到符号的地址,然后修正指令。

4 目标文件

Linux上,我们统称目标文件和可执行文件为ELF格式的文件,广义上他们几乎是一样的。

ELF文件有以下4大类:

  1. Relocatable File —— xx.o
  2. Executable File
  3. Shared Object File —— .so
  4. Core Dump File

目标文件中的段(section)

在这里插入图片描述
在这里插入图片描述

ELF文件结构

  1. 文件头-ELF Header
    可以使用readelf -h xx.o来查看文件头。
  2. 段表-Section Header Table
    使用readelf -S来查看ELF文件包含的段。
  3. 重定位表-Relocation Table0
    .rel.text.rel.data,记录重定位信息
  4. 字符串表
    把字符串集中起来存放到一个表里,然后通过使用偏移地址来引用字符串(结尾为空字符),包括.strtab(符号名的字符串)和.shstrtab(段名的字符串)

5 静态链接

1 空间与地址分配

扫描所有目标文件,收集所有的符号定义和符号引用,放到全局符号表中;计算出各个文件的各个段在合并后的位置以及长度,建立映射关系。

2 符号解析与重定位

在编译文件时,一些函数是在外部文件中定义的,编译器并不知道它的地址,就暂时将它们的地址设为0,真正的地址计算和修改则留给链接器。

那么链接器如何知道哪些指令中使用的地址需要重定位?这时就轮到重定位表发挥作用了,重定位表记录了每个符号的入口地址在表中的偏移地址。

【第3部分】装载与动态链接

1 装载的方式

  1. 覆盖装入:由程序员管理模块何时被加载到内存,该方式已被淘汰
  2. 页映射:以页为单元在磁盘和内存之间装载或置换数据

2 进程的启动

  1. 创建虚拟地址空间(通过MMU映射到物理内存)
  2. 读取可执行文件的文件头,建立虚拟地址空间和可执行文件的映射关系(用于加载可执行文件所在的页到内存)
  3. 将CPU指令寄存器设置成可执行文件入口

3 为什么需要动态链接?

  • 只使用静态链接,会造成内存和磁盘的浪费;
  • 使用静态链接时,如果某个模块更新,那么整个程序都要重新编译;

动态链接:等到程序开始运行时才进行链接。

4 动态链接的基本实现

程序装载时,动态链接器将所需要的动态库装载到进程地址空间,将所有未决议的符号绑定到相应的动态链接库,并进行重定位工作。

为了优化程序装载时进行链接的性能问题,采取了延迟绑定等方法。

cat /proc/xxxx/maps即可查看某个进程的的虚拟地址空间分布,其中可以看到部分引用的.so动态库所被映射的位置,其中有一个库为ld-x.x.so,这实际上就是linux的动态链接器,进程运行前会先跳转到动态链接器的代码中运行,完成链接工作后再跳转回进程代码运行。

5 位置无关码(PIC)

装载时重定位——把动态库的重定位也推迟到装载时进行。但有一个问题,动态链接库的代码在多个进程间共享,而重定位需要修改其指令,每个进程需要的修改可能不一样(比如跳转的地址不一样),那么就没法共享了。

PIC的基本思想:将指令中需要修改的部分分离出来,放到数据段中,这样指令部分就可以保持不变,而数据段对于每个进程都是有自己的独一份的。

模块间的数据访问:在数据段里建立一个指向外部变量的指针数组,即全局偏移表(Global Offset Table,GOT)。在编译时即确定GOT相对于当前指令的偏移,同时确定GOT中每个地址对应于哪个变量;模块装载时,加载器查找每个变量的实际地址,填充GOT的各个项。

如何区分动态库是否为PIC:readelf -d xx.so | grep TEXTREL,如果输出为空,则不是PIC。so库必须是PIC才能真正实现共享。

6 显式运行时链接(Explicit Run-time Linking)

或者叫运行时加载,即程序运行时自己指定加载的模块,且可以在不需要时将模块卸载。这可以用来实现插件、驱动等。程序可以通过4个API对动态库进行操作:

  • dlopen():加载动态库到进程地址空间
  • dlsym():找到所需的符号所在的地址
  • dlclose():卸载模块
  • dlerror():调用上面3个函数后,可以通过调用该函数判断前者调用是否成功

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

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

相关文章

通俗易懂,十分钟读懂DES,详解DES加密算法原理,DES攻击手段以及3DES原理。Python DES实现源码

文章目录1、什么是DES2、DES的基本概念3、DES的加密流程4、DES算法步骤详解4.1 初始置换(Initial Permutation,IP置换)4.2 加密轮次4.3 F轮函数4.3.1 拓展R到48位4.3.2 子密钥K的生成4.3.3 当前轮次的子密钥与拓展的48位R进行异或运算4.3.4 S盒替换(Subs…

学习 create-vite 源码后,感觉真不一样

前言 已经学习了一段时间的源码了,在写源码 demo 小例子的时候都是使用 react 项目作为模板,而我的 react 项目正好是由create-vite来创建的,因此,今天来学习一下关于create-vite的源码。话不多说,咱们直接开始学习。…

【深度学习】什么是线性回归逻辑回归单层神经元的缺陷

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录逻辑回归&线性回归单层神经元的缺陷单层神经元的缺陷逻辑回归&线性回归 线性回归预测的是一个连续值, 逻辑回归给出的”是”和“否”的回答. 等…

MySQL事务与索引

MySQL事务与索引 一、事务 1、事务简介 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。事务用来管理 insert,update,delete 语句 事务特性…

SQL性能优化的47个小技巧,果断收藏!

1、先了解MySQL的执行过程 了解了MySQL的执行过程,我们才知道如何进行sql优化。 客户端发送一条查询语句到服务器; 服务器先查询缓存,如果命中缓存,则立即返回存储在缓存中的数据; 未命中缓存后,MySQL通…

【编程入门】应用市场(go语言版)

背景 前面已输出多个系列: 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目,使…

qt源码--信号槽

本篇主要从Qt信号槽的连接、断开、调用、对象释放等方面展开; 1.信号建立连接过程 connect有多个重载函数,主要是为了方便使用者,比较常用的有2种方式: a. QObject::connect(&timer, &QTimer::timeout, &loop, &am…

一步步教你电脑变成服务器,tomcat的花生壳设置(原创)

1,首先你去https://console.oray.com/这网站注册个帐号,如果注册成功它会送你一个免费域名,当然不记得也没关系,你记住你注册的 帐号跟密码,然后下载它的软件(花生壳动态域名6.0正式版)有xp跟li…

19_FreeRTOS软件定时器

目录 软件定时器介绍 FreeRTOS软件定时器特点 软件定时器的命令队列 软件定时器的相关配置 单次定时器和周期定时器 软件定时器结构体成员 FreeRTOS软件定时器相关API函数 实验源码 软件定时器介绍 定时器描述:从指定的时刻开始,经过一个指定时间,然后触发一个超时事件…

操作系统权限提升(十三)之绕过UAC提权-MSF和CS绕过UAC提权

系列文章 操作系统权限提升(十二)之绕过UAC提权-Windows UAC概述 注:阅读本编文章前,请先阅读系列文章,以免造成看不懂的情况!! MSF和CS绕过UAC提权 CS绕过UAC提权 拿到一个普通管理员的SHELL,在CS中没有*号代表有…

样式冲突太多,记一次前端CSS升级

目前平台前端使用的是原生CSSBEM命名,在多人协作的模式下,容易出现样式冲突。为了减少这一类的问题,提升研效,我调研了业界上主流的7种CSS解决方案,并将最终升级方案落地到了工程中。 样式冲突的原因 目前遇到的样式…

数组:二分查找、移除数组等经典数组题

二分查找:相关题目链接:https://leetcode.cn/problems/binary-search/题目重现:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值…

【c++】文件操作(文本文件、二进制文件)

文章目录文件操作文本文件写文件读文件二进制文件写文件读文件文件操作 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放; 通过文件可以将数据持久化; c中对文件操作需要包含头文件 文件类型分为两种: 1、文本文…

Playbook的用法

目录 Playbook Playbook 与 Ad-Hoc 对比 YAML 语言特性 YAML语法简介 支持的数据类型 写法格式 1 scalar 标量 建议缩进两个空格,可多 2 Dictionary 字典 3 List 列表 三种常见的数据格式 Playbook 核心组件 不要用 tab 可以#注释 hosts remote_us…

【编程入门】应用市场(Python版)

背景 前面已输出多个系列: 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目,使…

【Linux】进程间通信(匿名管道和命名管道通信、共享内存通信)

文章目录1、进程间通信1.1 进程的通信1.2 如何让进程间通信?1.3 进程间通信的本质2、管道通信2.1 匿名管道2.2 匿名管道通信2.3 命名管道2.4 命名管道的通信3、SystemV中的共享内存通信3.1 共享内存3.2 共享内存的通信3.3 共享内存的缺点以及数据保护3.4 共享内存的…

13.STM32超声波模块讲解与实战

目录 1.超声波模块讲解 2.超声波时序图 3.超声波测距步骤 4.项目实战 1.超声波模块讲解 超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。电路板上有4个引脚:VCC GND Trig(触发)&#xff…

gcc的使用,调试工具gdb的使用

gcc编译 gcc编译可以分为四个步骤,预处理、编译、汇编、链接。 预处理命令:gcc -E hello.c -o hello.i编译命令:gcc -S hello.i -o hello.s汇编命令: gcc -c hello.s -o hello.o链接命令:gcc hello.o -o hello gcc…

一个.Net Core开发的,撑起月6亿PV开源监控解决方案

更多开源项目请查看:一个专注推荐.Net开源项目的榜单 项目发布后,对于我们程序员来说,项目还不是真正的结束,保证项目的稳定运行也是非常重要的,而对于服务器的监控,就是保证稳定运行的手段之一。对数据库、…

Navicat16实用小技巧

数据库管理工具是一种用于管理数据库的软件工具,它可以帮助用户创建、修改、维护和查询数据库。数据库管理工具可以为用户提供可视化界面,使得管理数据库变得更加容易。最为一款数据库管理工具,需要具备一下功能: 数据库创建和配…